JZOJ4838. I Like Matrix!

来源:互联网 发布:客服中心数据分析 编辑:程序博客网 时间:2024/05/17 22:11

题目大意

给定一个n×m的全零矩阵和q次操作
每次操作有四种:

  1. 1 i j把矩阵(i,j)取反
  2. 2 i把第i行取反
  3. 3 j把第j列取反
  4. 4 k回到第k次操作以后

求每次操作完成之后矩阵元素之和。

Data Constraint
n,m1000,q100000

题解

对于每个操作,我们可以在对应的状态间连边,构出一棵操作树。
然后我们沿边DFS每次暴力修改和撤销。

时间复杂度:O(nq)

SRC

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;#define N 1000 + 10#define M 100000 + 10struct 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 ;}

以上.

2 0
原创粉丝点击