[cf707D]Persistent Bookcase
显然可以写可持久化树套树,然而实际上由于只有一整行的修改和单点修改,并没有一个小矩形的修改,所以可以将其转化到一个序列上,只需要写可持久化线段树就可以了(然而标算是操作树)。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define ll long long 6 #define mid ((l+r)>>1) 7 #define L(k) f[k].l 8 #define R(k) f[k].r 9 #define maxN 1000001 10 #define maxT 100001 11 struct ji{ 12 int l,r,lazy,sum; 13 }f[4*maxN+20*maxT]; 14 int N,n,m,q,p,k,x,y,now,R[maxT]; 15 void up(int k,int l,int r){ 16 f[k].sum=f[L(k)].sum+f[R(k)].sum; 17 if (f[k].lazy)f[k].sum=r-l+1-f[k].sum; 18 } 19 void build(int &k,int l,int r){ 20 k=++N; 21 if (l==r)return; 22 build(L(k),l,mid); 23 build(R(k),mid+1,r); 24 up(k,l,r); 25 } 26 void update(int &root,int k,int l,int r,int x,int y){ 27 if ((r<x)||(l>x))return; 28 f[root=++N]=f[k]; 29 if (l==r){ 30 f[root].sum=y; 31 return; 32 } 33 y^=f[k].lazy; 34 update(L(root),L(k),l,mid,x,y); 35 update(R(root),R(k),mid+1,r,x,y); 36 up(root,l,r); 37 } 38 void update2(int &root,int k,int l,int r,int x,int y){ 39 if ((y<l)||(r<x))return; 40 f[root=++N]=f[k]; 41 if ((x<=l)&&(r<=y)){ 42 f[root].lazy^=1; 43 f[root].sum=r-l+1-f[root].sum; 44 return; 45 } 46 update2(L(root),L(k),l,mid,x,y); 47 update2(R(root),R(k),mid+1,r,x,y); 48 up(root,l,r); 49 } 50 int main(){ 51 scanf("%d%d%d",&n,&m,&q); 52 build(R[0],1,n*=m); 53 for(int i=1;i<=q;i++){ 54 scanf("%d%d",&p,&x); 55 now++; 56 if (p<=2){ 57 scanf("%d",&y); 58 update(R[i],R[i-1],1,n,(x-1)*m+y,p&1); 59 } 60 if (p==3)update2(R[i],R[i-1],1,n,(x-1)*m+1,x*m); 61 if (p==4)R[i]=R[x]; 62 printf("%d\n",f[R[i]].sum); 63 } 64 }