B. Tokitsukaze and Meeting_思維
阿新 • • 發佈:2022-05-13
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
小結:
很好的思維題,做題的時候不能懶,要多做樣例多找規律。
想不明白的時候就多寫寫樣例。