zoukankan      html  css  js  c++  java
  • luoguP2137 Gty的妹子树 分块+主席树+DFS序

    对于一类带修改问题可以采用对时间(操作)分块,然后定期重构的方式来维护.   

    设块的大小为 $B$,则重构 $frac{Q}{B}$ 次,每次查询的复杂度为 $O(B log n)$.     

    计算一下 $B$ 的大小来平衡重构和查询的复杂度即可.   

    这种纯数据结构题都挺好写的.  

    code: 

    #include <cstdio>   
    #include <vector>      
    #include <cstring> 
    #include <algorithm>    
    #define N 60009   
    #define ll long long 
    #define INF 1000000  
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;   
    const int B=600;                     
    int n,edges,tim,tot,cn,cnt; 
    vector<int>G;   
    int dfn[N<<1],bu[N<<1],ed[N<<1],rt[N<<1],A[N<<1],IN[N<<1];        
    int hd[N<<1],to[N<<2],nex[N<<2],fa[19][N<<1],val[N<<1],dep[N<<1];           
    struct data { 
        int ls,rs,sum;     
        data() { ls=rs=sum=0; }  
    }s[N*50];  
    void add(int u,int v) {  
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;  
    }    
    void dfs(int x,int ff) {   
        fa[0][x]=ff;
        dep[x]=dep[ff]+1;     
        dfn[x]=++tim,bu[tim]=x;  
        for(int i=hd[x];i;i=nex[i])
            if(to[i]!=ff) dfs(to[i],x);   
        ed[x]=tim;   
    }        
    int update(int pre,int l,int r,int p,int v) {  
        int now=++tot;   
        s[now]=s[pre];    
        s[now].sum+=v;  
        if(l==r) return now;   
        int mid=(l+r)>>1;  
        if(p<=mid)  s[now].ls=update(s[pre].ls,l,mid,p,v);   
        else s[now].rs=update(s[pre].rs,mid+1,r,p,v);   
        return now;    
    }
    int query(int x,int l,int r,int L,int R) {  
        if(!x) return 0;  
        if(l>=L&&r<=R) return s[x].sum;  
        int mid=(l+r)>>1,re=0; 
        if(L<=mid)  re+=query(s[x].ls,l,mid,L,R);  
        if(R>mid)   re+=query(s[x].rs,mid+1,r,L,R);  
        return re;   
    }
    void CON() {                
        for(int i=1;i<=tot;++i) s[i]=data();      
        tot=0,rt[0]=0,tim=0,cnt=0; 
        dfs(1,0);   
        int x,y,z;   
        for(int i=1;i<=n;++i)   A[++cnt]=val[i];   
        sort(A+1,A+1+cnt);                                      
        for(int i=1;i<=n;++i) {    
            z=lower_bound(A+1,A+1+cnt,val[bu[i]])-A;         
            rt[i]=update(rt[i-1],1,INF,z,1);   
        }     
        for(int i=0;i<G.size();++i) IN[G[i]]=0;  
        G.clear();   
    }
    int get_lca(int x,int y) {   
        if(dep[x]!=dep[y]) {  
            if(dep[x]>dep[y]) swap(x,y);   
            for(int i=18;i>=0;--i) if(dep[fa[i][y]]>=dep[x]) y=fa[i][y];    
        }  
        if(x==y) return x;     
        for(int i=18;i>=0;--i) {  
            if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];  
        }  
        return fa[0][x];    
    }
    int main() {
        // setIO("input");                  
        int x,y,z,m;   
        scanf("%d",&n);  
        for(int i=1;i<n;++i) {  
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);  
        }   
        for(int i=1;i<=n;++i) scanf("%d",&val[i]);  
        CON();    
        for(int i=1;i<19;++i) 
            for(int j=1;j<=n;++j) fa[i][j]=fa[i-1][fa[i-1][j]];       
        scanf("%d",&m);   
        int POS=n,lastans=0;             
        for(int i=1;i<=m;++i) {  
            scanf("%d%d%d",&z,&x,&y);  
            x^=lastans,y^=lastans;    
            if(z==0) {            
                int tmp=y;   
                // x 中 大于 y 的   
                // 原树中的答案        
                if(y+1>A[cnt]) y=INF;  
                else y=lower_bound(A+1,A+1+cnt,y+1)-A;                                         
                int ans=query(rt[ed[x]],1,INF,y,INF)-query(rt[dfn[x]-1],1,INF,y,INF);  
                for(int j=0;j<G.size();++j) {          
                    int p=G[j];  
                    if(dfn[p]>=dfn[x]&&dfn[p]<=ed[x]) {             
                        int ori=query(rt[dfn[p]],1,INF,y,INF)-query(rt[dfn[p]-1],1,INF,y,INF); 
                        if(ori&&val[p]<=tmp) --ans;   
                        if(!ori&&val[p]>tmp) ++ans;              
                    }
                }                          
                for(int j=POS+1;j<=n;++j) if(get_lca(j,x)==x&&val[j]>tmp) ++ans; 
                printf("%d
    ",lastans=ans);       
            } 
            if(z==1) {                
                ++cn,val[x]=y;     
                if(x<=POS&&!IN[x]) G.push_back(x),IN[x]=1;       
            } 
            if(z==2) {     
                ++cn,++n;   
                val[n]=y,fa[0][n]=x,add(fa[0][n],n),dep[n]=dep[x]+1;       
                for(int j=1;j<19;++j) fa[j][n]=fa[j-1][fa[j-1][n]];     
                if(cn>B) CON(),POS=n,cn=0;   
            }
        }
        return 0; 
    }
    

      

  • 相关阅读:
    Passing Reference by value
    WPF中override ResourceDictionary中的设置的方法
    WPF中TextBox的PreviewMouseLeftButtonUp事件
    Attribute的理解和认识
    IIS添加服务
    Unix时间戳转换成C#中的DateTime
    KMP算法的实现
    IDA 宏定义
    实验吧-catalyst-system
    python整数转ASCII码
  • 原文地址:https://www.cnblogs.com/guangheli/p/13206385.html
Copyright © 2011-2022 走看看