CF707D Persistent Bookcase 可持久化线段树

维护一个二维零一矩阵(n,m<=1000),支持四种操作(不超过10^5次):

  • 将(i,j)置一
  • 将(i,j)置零
  • 将第i行零一反转yu
  • 回到第K次操作前的状态
  • 每次操作后输出全局一共有多少个一

你发现如果每一次操作都复制一整行的话是可以用 $bitset$ 优化的,自带/32 

所以,我们对于每一个时刻维护一个线段树,其中 $i$ 节点表示第 $i$ 行对应的 $bitset$ 编号.  

对于前 $3$ 个操作,每一次操作时都暴力新建一个 bitset,然后每次在可持久化线段树上最多更新一个单点. 

顺便在线段树的节点上再维护一个 $1$ 的数量即可. 

#include <bits/stdc++.h>  
#define M 1004 
#define N 100005      
#define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) 
using namespace std; 
bitset<M>v[N],uni,oo;       
int rt[N]; 
namespace seg
{  
    #define lson t[x].ls 
    #define rson t[x].rs  
    int tot; 
    int newnode() { return ++ tot; }    
    struct Node 
    {
        int ls,rs,id,sum;        
    }t[N*40]; 
    int update(int x,int l,int r,int p,int v) 
    {    
        int now=newnode(); 
        t[now]=t[x];           
        if(l==r) 
        {
            t[now].id=v;    
            return now; 
        }
        int mid=(l+r)>>1;   
        if(p<=mid) 
        {
            t[now].ls=update(lson,l,mid,p,v); 
        }
        else 
        {
            t[now].rs=update(rson,mid+1,r,p,v);    
        }
        t[now].sum=t[t[now].ls].sum+t[t[now].rs].sum;   
        return now;    
    }
    int modify(int x,int l,int r,int p,int v) 
    {
        int now=newnode();  
        t[now]=t[x];      
        if(l==r) 
        {
            t[now].sum=v;      
            return now; 
        }
        int mid=(l+r)>>1; 
        if(p<=mid) t[now].ls=modify(lson,l,mid,p,v); 
        else t[now].rs=modify(rson,mid+1,r,p,v); 
        t[now].sum=t[t[now].ls].sum+t[t[now].rs].sum;          
        return now; 
    }
    int query(int x,int l,int r,int p) 
    {
        if(!x) return 0; 
        if(l==r)  return t[x].id; 
        int mid=(l+r)>>1;   
        if(p<=mid) return query(lson,l,mid,p); 
        else return query(rson,mid+1,r,p);   
    }  
    void dfs(int x,int l,int r) 
    {
        if(!x) return;       
        if(l==r) printf("%d %d\n",l,t[x].sum);   
        int mid=(l+r)>>1;        
        dfs(lson,l,mid), dfs(rson,mid+1,r); 
    }
    #undef lson 
    #undef rson   
}; 
int main() 
{ 
    // setIO("now"); 
    int n,m,q,i,j; 
    scanf("%d%d%d",&n,&m,&q);           
    for(i=1;i<=m;++i) uni[i]=1;    
    for(i=1;i<=q;++i) 
    {
        int op,a,b,c; 
        scanf("%d",&op);       
        rt[i]=rt[i-1];      
        if(op==1)
        {  
            scanf("%d%d",&a,&b);           
            int pre=seg::query(rt[i-1],1,n,a);         
            v[i]=v[pre];   
            v[i][b]=1;           
            rt[i]=seg::update(rt[i-1],1,n,a,i);                
            oo=v[i]&uni;     
            rt[i]=seg::modify(rt[i],1,n,a,oo.count());       
        } 
        if(op==2) 
        { 
            scanf("%d%d",&a,&b);   
            int pre=seg::query(rt[i-1],1,n,a);      
            v[i]=v[pre]; 
            v[i][b]=0;                                                               
            rt[i]=seg::update(rt[i-1],1,n,a,i);       
            oo=v[i]&uni;                             
            rt[i]=seg::modify(rt[i],1,n,a,oo.count()); 
        }
        if(op==3) 
        {   
            int x; 
            scanf("%d",&x);    
            int pre=seg::query(rt[i-1],1,n,x);    
            v[i]=v[pre]^uni;     
            rt[i]=seg::update(rt[i-1],1,n,x,i);
            oo=v[i]&uni;        
            rt[i]=seg::modify(rt[i],1,n,x,oo.count());           
        } 
        if(op==4) 
        {
            int x; 
            scanf("%d",&x);    
            rt[i]=rt[x];                
        }
        printf("%d\n",seg::t[rt[i]].sum);   
    }
    return 0; 
}

  

posted @ 2019-10-22 16:02  EM-LGH  阅读(182)  评论(0编辑  收藏  举报