F. Desktop Rearrangement

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;
  }
}
 
posted @ 2022-05-25 17:08  Pan_c  阅读(98)  评论(0)    收藏  举报