题目链接:codeforces.com/contest/707/problem/D
这个题用了比较巧妙的dfs 我们先来看 1,2,3 操作 这三个都很好做 我们维护1000个bitset 在相应的书架上进行操作就好
关键是4操该如何维护 乍一看这像是维护历史信息 得用可持久化的数据结构 后来我看了题解之后豁然开朗
大家可以看链接:https://blog.csdn.net/queuelovestack/article/details/52269321
大概意思就是我们根据询问建立起来一颗dfs树 对于4操作 我们不用回去 只需要连接一条k到i的边 然后按dfs走就能保证正确性
可以看看 那个博客的图 了解一下
#include<bits/stdc++.h>
using namespace std;
const int N = 1002;
const int M = 1e5+10;
bitset<N> b[N],c;
int h[M],to[M<<1],nex[M<<1],cur,op[M],l[M],r[M],ans[M];
void add_edge(int x,int y){
to[++cur]=y;nex[cur]=h[x];h[x]=cur;
}
void dfs(int u){
if(!u){
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
dfs(v);
}
}
bool flag=false;
if(op[u]==1){
if(!b[l[u]].test(r[u])) flag=true,ans[u]++,b[l[u]].set(r[u]);
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
ans[v]=ans[u];
dfs(v);
}
if(flag) b[l[u]].reset(r[u]);
}else if(op[u]==2){
if(b[l[u]].test(r[u])) flag=true,ans[u]--,b[l[u]].reset(r[u]);
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
ans[v]=ans[u];
dfs(v);
}
if(flag) b[l[u]].set(r[u]);
}else if(op[u]==3){
ans[u]-=b[l[u]].count();
b[l[u]]^=c;
ans[u]+=b[l[u]].count();
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
ans[v]=ans[u];
dfs(v);
}
b[l[u]]^=c;
}else if(op[u]==4){
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
ans[v]=ans[u];
dfs(v);
}
}
}
int main(){
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
for(int i = 1; i <= m; i++) c.set(i);
for(int i = 1; i <= q; i++){
scanf("%d",&op[i]);
if(op[i]<3){
scanf("%d%d",&l[i],&r[i]);
}else scanf("%d",&l[i]);
if(op[i]<4) add_edge(i-1,i);
else add_edge(l[i],i);
}
dfs(0);
for(int i = 1; i <= q; i++) printf("%d\n",ans[i]);
return 0;
}