CF707D Persistent Bookcase (可持久化线段树+区间修改)

//cf707d
/*
 题意:维护一个图,支持四种操作
 1.第i行第j列变为1
 2.第i行第j列变为0
 3.第i行颠倒,1变0,0变1
 4.将整张图变为第k次操作时的状态,如果k是0的话,则清空图
*/

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+100;
const int M=maxn*6;
struct node {
    int l,r,lazy,sum;
}segTree[M];
int T[maxn];
int tot,n,m,q;
void pushdown (int i,int l,int r) {
    segTree[i].sum=segTree[segTree[i].l].sum+segTree[segTree[i].r].sum;
    if (segTree[i].lazy) segTree[i].sum=r-l+1-segTree[i].sum;
}

void build (int &rt,int l,int r) {
    rt=++tot;
    if (l==r) return;
    int mid=(l+r)>>1;
    build(segTree[rt].l,l,mid);
    build(segTree[rt].r,mid+1,r);
    pushdown(rt,l,r);
}
void up (int &rt,int k,int l,int r,int x,int y) {
    if (r<x||l>x) return;
    rt=++tot;
    segTree[rt]=segTree[k];
    if (l==r) {
        segTree[rt].sum=y;
        return;
    }
    y^=segTree[k].lazy;
    int mid=(l+r)>>1;
    up(segTree[rt].l,segTree[k].l,l,mid,x,y);
    up(segTree[rt].r,segTree[k].r,mid+1,r,x,y);
    pushdown(rt,l,r);
}
void up2 (int &rt,int k,int l,int r,int x,int y) {
    if (r<x||l>y) return;
    rt=++tot;
    segTree[rt]=segTree[k];
    if (x<=l&&y>=r) {
        segTree[rt].lazy^=1;
        segTree[rt].sum=r-l+1-segTree[rt].sum;
        return;
    }
    int mid=(l+r)>>1;
    up2(segTree[rt].l,segTree[k].l,l,mid,x,y);
    up2(segTree[rt].r,segTree[k].r,mid+1,r,x,y);
    pushdown(rt,l,r);
}

int main () {
    scanf("%d%d%d",&n,&m,&q);
    build(T[0],1,n*m);
    for (int i=1;i<=q;i++) {
        int p,x;
        scanf("%d%d",&p,&x);
        if (p<=2) {
            int y;
            scanf("%d",&y);
            up(T[i],T[i-1],1,n*m,(x-1)*m+y,p&1);
        }
        if (p==3) {
            up2(T[i],T[i-1],1,n*m,(x-1)*m+1,x*m);
        }
        if (p==4) 
            T[i]=T[x];
        printf("%d
",segTree[T[i]].sum);
    }
}