题目大意
给定一个
n×m
的全零矩阵和
q
次操作
每次操作有四种:
1 i j 把矩阵 (i,j) 取反- 2 i 把第 i 行取反
3 j 把第 j 列取反4 k 回到第 k 次操作以后
求每次操作完成之后矩阵元素之和。
Data Constraint
题解
对于每个操作,我们可以在对应的状态间连边,构出一棵操作树。
然后我们沿边DFS每次暴力修改和撤销。
时间复杂度: O(nq)
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 1000 + 10
#define M 100000 + 10
struct Operator {
int type ;
int x , y ;
Operator ( int T = 0 , int X = 0 , int Y = 0 ) { type = T , x = X , y = Y ; }
} OP[M] ;
int Node[M] , Next[M] , Head[M] , tot ;
int Mat[N][N] , Ans[M] ;
int n , m , Q , Cnt ;
void link( int u , int v ) {
Node[++tot] = v ;
Next[tot] = Head[u] ;
Head[u] = tot ;
}
void Modify( Operator t ) {
int op = t.type ;
int x = t.x , y = t.y ;
if ( op == 1 ) {
Mat[x][y] = !Mat[x][y] ;
Cnt += ( Mat[x][y] ? 1 : -1 ) ;
} else if ( op == 2 ) {
for (int j = 1 ; j <= m ; j ++ ) {
if ( Mat[x][j] ) Cnt -- ;
else Cnt ++ ;
Mat[x][j] ^= 1 ;
}
} else if ( op == 3 ) {
for (int j = 1 ; j <= n ; j ++ ) {
if ( Mat[j][y] ) Cnt -- ;
else Cnt ++ ;
Mat[j][y] ^= 1 ;
}
}
}
void DFS( int x ) {
if ( x ) Modify( OP[x] ) ;
Ans[x] = Cnt ;
for (int p = Head[x] ; p ; p = Next[p] ) DFS( Node[p] ) ;
if ( x ) Modify( OP[x] ) ;
}
int main() {
freopen( "present.in" , "r" , stdin ) ;
freopen( "present.out" , "w" , stdout ) ;
scanf( "%d%d%d" , &n , &m , &Q ) ;
for (int i = 1 ; i <= Q ; i ++ ) {
int op ;
scanf( "%d" , &op ) ;
if ( op == 1 ) {
int x , y ;
scanf( "%d%d" , &x , &y ) ;
OP[i] = Operator( op , x , y ) ;
link( i - 1 , i ) ;
} else if ( op == 2 ) {
int x ;
scanf( "%d" , &x ) ;
OP[i] = Operator( op , x , 0 ) ;
link( i - 1 , i ) ;
} else if ( op == 3 ) {
int y ;
scanf( "%d" , &y ) ;
OP[i] = Operator( op , 0 , y ) ;
link( i - 1 , i ) ;
} else {
int k ;
scanf( "%d" , &k ) ;
OP[i] = Operator( op , 0 , 0 ) ;
link( k , i ) ;
}
}
DFS(0) ;
for (int i = 1 ; i <= Q ; i ++ ) printf( "%d\n" , Ans[i] ) ;
return 0 ;
}
以上.