F. Desktop Rearrangement

【题意】:
给你一个n*m的矩阵 , ’ * ‘ 代表图标,‘ . ’代表空白。如果所有的*从上到下从左到右(先排满第一列列,再排满第二列等等)排列好,那么就是好的桌面。
k次询问,每次询问将(x,y)点翻转(*变成 ’ . ‘ , ‘ . ’变成 * )。每次询问中你可以进行若干次操作,每次操作将任意两个位置互换。问每次询问的时,将其变成好的桌面的时候要多少次操作。
【思路】:
将矩阵变成一列,(x,y)的 坐标 在列中的下标是 (y-1)*n+x 。
然后记录整个桌面里有多少个*,记为cnt。说明前cnt的位置要变成 * 。
在记录前缀和数组 a , 每次查询前cnt个里有多少个 * , 然后用 总的星号数cnt - 前缀和 a[cnt] 就 是最后答案。
【代码】:
ll lowbit( ll x ){
return x & (-x) ;
}
void add(ll x,ll y ){
for ( ll i=x;i<=n*m;i += lowbit(i) ){
a[i] += y ;
// test2(i,a[i]);
}
}
ll sum( ll x ){
ll res = 0 ;
for ( ll i=x;i;i -= lowbit(i) ){
res += a[i];
}
return res;
}
void solve() {
cin>>n>>m>>k;
ll x , y , cnt = 0 ;
ms(a,0);
rep(i,1,n) rep(j,1,m) cin>>s[(j-1)*n+i];
// rep(i,1,n*m) cout<<s[i];
// cout<<endl;
rep(i,1,n*m){
if ( s[i]== '*' ){
add(i,1);
cnt++;
}
}
// rep(i,1,n*m) test2(i,a[i]);
while ( k-- ){
cin>>x>>y;
ll g = (y-1)*n+x;
if ( s[ g ] =='*' ){
s[ g ] = '.' ;
add( g , -1 ) ;
cnt -- ;
}else {
s [ g ] = '*' ;
add( g , 1 ) ;
cnt ++ ;
}
cout<< cnt - sum(cnt) <<endl;
}
}

浙公网安备 33010602011771号