1. 程式人生 > 其它 >B. Tokitsukaze and Meeting_思維

B. Tokitsukaze and Meeting_思維

B. Tokitsukaze and Meeting_思維

題目大意:

n*m的座位。班級裡有0有1,給01串表示大家進入班級就坐的次序,每一時刻進一個人。每個人都會坐在(1,1)座位,其他所有人右移一位。一行或一列在其中有1的情況下被認為是好的。現在要求出對於每一個時刻,好行和好列的和。

思路和程式碼:

很好的思維題。窩覺得比較難。

首先比較好考慮的是,行列分開計算。

考慮行

resrow[i]表示第i個人進來時行的答案。

對於行來說,第二行到最後一行我們都是算過的。也就是說,我們可以有以下式子:resrow[i]=resrow[i-m]+{第一行是否是好行}

對於第一行是否good,我們只需要維護第一行的1的數量即可。

考慮列

rescol[i]表示第i個人進來時列的答案。

對於列來說,第i層的[2,m]列就是第i-1層的[1,m-1]列。

而且觀察每一列的數值的下標可以發現,每一列的所有下標對m取模的值都是相同的。所以我們就可以維護一個col[j%m]來維護某一列是否有1。

void solve(){
	cin >> n >> m ;
	
	string s ; cin >> s ;
	s = " " + s ;
	
	vct<int> rescol(n * m + 1 , 0) ;
	vct<int> resrow(n * m + 1 , 0) ;
	int row1 = 0 ;//維護第一行1的數量 
	vct<int> col(m + 1 , 0) ;//維護所有的m列的1數量 
	
	rep(i , 1 , n * m){
		//resrow
		if(i <= m){
			resrow[i] = resrow[i - 1] ;
			if(s[i] == '1'){
				if(!row1) resrow[i] ++ ;
				row1 ++ ;
			}
			continue ;
		}
		if(s[i - m] == '1') row1 -- ;
		//第一行的最後一個1被頂到第二行去了
		row1 += s[i] == '1' ;
		resrow[i] = resrow[i - m] + (row1 > 0) ;
	}
	
	rep(i , 1 , n * m){
		//rescol
		rescol[i] = rescol[i - 1] ;
		if(s[i] == '1'){
			if(!col[i % m]) rescol[i] ++ ;
			col[i % m] ++ ;
		}
	}
	rep(i , 1 , n * m)
	cout << rescol[i] + resrow[i] << " \n"[i == n * m] ;
	 
}//code_by_tyrii 

小結:

很好的思維題,做題的時候不能懶,要多做樣例多找規律。

想不明白的時候就多寫寫樣例。