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
小结:
很好的思维题,做题的时候不能懒,要多做样例多找规律。
想不明白的时候就多写写样例。
标签:思维,rescol,第一行,rep,resrow,Tokitsukaze,一列,Meeting,col 来源: https://www.cnblogs.com/tyriis/p/16266143.html