对一个 n ∗ m 的零矩阵 A 进行 q 次操作:
• 1 i j:将 Ai,j 取反;
• 2 i:将矩阵 A 第 i 行的所有元素全部取反;
• 3 j:将矩阵 A 第 j 列的所有元素全部取反;
• 4 k:将矩阵 A 还原为第 k 次操作之后的状态。
进行每一次操作之后,询问当前矩阵所有元素的和。
Input
第一行包含三个整数 n,m 和 q。
之后 q 行每行包含两个或三个整数,表示一次操作的所有参数。
Output
共 q 行每行包含一个整数 ans,表示当前矩阵所有元素的和。
这是一个需要快读快输的玩意儿。。。
主要是模拟,然后建立处理时间的关系。(比如4操作的话直接在回到的那个点继续搜什么的)然后处理完每一步返回,每一步计算,最后用一个Ans存起来。
#include<cstdio>
int l[100005],Ans[100005],n,m,k,f[1005][1005],tt,C[100005],X[100005],Y[100005],Sum;
struct asdf{
int to,next;
} lu[100005];
int read(){ //快读
char cc=getchar();
int x=0;
while(cc>'9'||cc<'0') cc=getchar();
while(cc>='0'&&cc<='9'){
x=x*10+cc-48;
cc=getchar();
}
return x;
}
void put(int l){ //快输
if(l>9) put(l/10);
putchar(l%10+48);
}
void G(int kk){ //处理/回溯
if(C[kk]==1){
Sum+=1-(f[X[kk]][Y[kk]]<<1); //神奇玩意
f[X[kk]][Y[kk]]^=1;
}
else if(C[kk]==2)
for(int i=1;i<=m;++i){
Sum+=1-(f[X[kk]][i]<<1);
f[X[kk]][i]^=1;
}
else if(C[kk]==3)
for(int i=1;i<=n;++i){
Sum+=1-(f[i][X[kk]]<<1);
f[i][X[kk]]^=1;
}
}
void s(int kk){ //dfs
G(kk);
Ans[kk]=Sum;
for(int i=l[kk];i;i=lu[i].next) //它接下来要处理的命令编号
s(lu[i].to);
G(kk);
}
void lj(int aa,int bb){ //将aa结点与bb结点链接,说明aa处理完后可以处理bb
lu[++tt].to=bb;
lu[tt].next=l[aa];
l[aa]=tt;
}
int main(){
int t;
n=read();
m=read();
k=read();
for(int i=1;i<=k;++i){ //i,命令序号
C[i]=read();X[i]=read(); //随意的一个读入。
if(C[i]==1) Y[i]=read();
if(C[i]==4) lj(X[i],i); //如果需要回溯,那么回溯到的那个点可以直接处理此操作。。。
else lj(i-1,i); //不然就从上一步到这里
}
s(0); //注意有一些是回溯到0号命令的
for(int i=1;i<=k;++i,putchar('\n')) //快输
put(Ans[i]);
}