可以根据关系连边 形成树结构 然后dfs+回溯
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
const int N=300005,M=1005;
struct edge{
int u,v,next;
}G[N];
int head[N],inum;
inline void add(int u,int v,int p){
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
struct abcd{
int t,x,y,o;
}W[N];
int n,m;
bool Map[M][M],tag[M];
int num1[M],num2[M];
int ans[N],cur;
inline void Deal(abcd &R){
if (R.t==1 && !(Map[R.x][R.y]^tag[R.x])) Map[R.x][R.y]^=1,cur++,num1[R.x]++,num2[R.x]--,R.o=1;
if (R.t==2 && (Map[R.x][R.y]^tag[R.x])) Map[R.x][R.y]^=1,cur--,num1[R.x]--,num2[R.x]++,R.o=1;
if (R.t==3) tag[R.x]^=1,cur+=num2[R.x]-num1[R.x],swap(num1[R.x],num2[R.x]);
}
inline void Undeal(abcd &R){
if (R.t==1 && R.o) Map[R.x][R.y]^=1,cur--,num1[R.x]--,num2[R.x]++;
if (R.t==2 && R.o) Map[R.x][R.y]^=1,cur++,num1[R.x]++,num2[R.x]--;
if (R.t==3) tag[R.x]^=1,cur+=num2[R.x]-num1[R.x],swap(num1[R.x],num2[R.x]);
}
#define V G[p].v
inline void dfs(int u){
Deal(W[u]);
ans[u]=cur;
for (int p=head[u];p;p=G[p].next)
dfs(V);
Undeal(W[u]);
}
int main(){
int Q;
freopen("bookcase.in","r",stdin);
freopen("bookcase.out","w",stdout);
read(n); read(m); read(Q);
for (int i=1;i<=Q;i++){
read(W[i].t); read(W[i].x);
if (W[i].t<=2) read(W[i].y);
if (W[i].t==4)
add(W[i].x,i,++inum);
else
add(i-1,i,++inum);
}
for (int i=1;i<=n;i++) num1[i]=0,num2[i]=m;
dfs(0);
for (int i=1;i<=Q;i++)
printf("%d\n",ans[i]);
return 0;
}