• 树链剖分——NOI2015


    8说了上代码

    给定一棵树,两种操作
    a x:x->root路径上的点权值置1
    b x: 把x的子树所有结点权值置0 
    树上的区间更新操作,显然是要维护dfs
    第一个操作暴力显然是t,用树剖把复杂度降到log^2n级 
    线段树上:区间置1|0 
    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 100005
    struct Edge{int to,nxt;}edge[maxn<<1]; 
    int head[maxn],tot,n,q;
    
    int f[maxn],son[maxn],size[maxn],d[maxn];
    void dfs1(int x,int pre,int deep){
        size[x]=1;d[x]=deep;f[x]=pre;
        for(int i=head[x];i!=-1;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==pre)continue;
            dfs1(y,x,deep+1);
            size[x]+=size[y];
            if(size[y]>size[son[x]])son[x]=y;
        }
    }
    int top[maxn],id[maxn],rk[maxn],cnt;
    void dfs2(int x,int tp){
        top[x]=tp;id[x]=++cnt;rk[cnt]=x;
        if(son[x])dfs2(son[x],tp);
        for(int i=head[x];i!=-1;i=edge[i].nxt){
            int y=edge[i].to;
            if(y!=son[x] && y!=f[x])dfs2(y,y);
        }
    }
    
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    int sum[maxn<<2],lazy[maxn<<2];
    void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
    void pushdown(int l,int r,int rt){
        if(lazy[rt]<0)return;
        if(lazy[rt]==0){
            lazy[rt<<1]=lazy[rt<<1|1]=0;
            sum[rt<<1]=sum[rt<<1|1]=0;
            lazy[rt]=-1; 
        } 
        if(lazy[rt]==1){
            int m=l+r>>1;
            lazy[rt<<1]=lazy[rt<<1|1]=1;
            sum[rt<<1]=m-l+1;sum[rt<<1|1]=r-m;
            lazy[rt]=-1;
        }
    }
    void set0(int L,int R,int l,int r,int rt){
        if(L<=l && R>=r){lazy[rt]=0;sum[rt]=0;return;}
        pushdown(l,r,rt);
        int m=l+r>>1;
        if(L<=m)set0(L,R,lson);
        if(R>m)set0(L,R,rson);
        pushup(rt);
    }
    void set1(int L,int R,int l,int r,int rt){
        if(L<=l && R>=r){lazy[rt]=1;sum[rt]=r-l+1;return;}
        pushdown(l,r,rt);
        int m=l+r>>1;
        if(L<=m)set1(L,R,lson);
        if(R>m)set1(L,R,rson);
        pushup(rt);
    }
    int query(int L,int R,int l,int r,int rt){
        if(L<=l &&R >=r)return sum[rt];
        int m=l+r>>1,res=0;
        pushdown(l,r,rt);
        if(L<=m)res+=query(L,R,lson);
        if(R>m)res+=query(L,R,rson);
        return res;
    }
    
    void Set1(int x,int y){
        while(top[x]!=top[y]){
            if(d[top[x]]<d[top[y]])swap(x,y);
            set1(id[top[x]],id[x],1,n,1);
            x=f[top[x]];
        }
        if(id[x]>id[y])swap(x,y);
        set1(id[x],id[y],1,n,1);
    }
    int Query(int x,int y){
        int res=0;
        while(top[x]!=top[y]){
            if(d[top[x]]<d[top[y]])swap(x,y);
            res+=query(id[top[x]],id[x],1,n,1);
            x=f[top[x]];
        }
        if(id[x]>id[y])swap(x,y);
        return res+query(id[x],id[y],1,n,1);
    }
    
    void init(){
        memset(head,-1,sizeof head);
        memset(lazy,-1,sizeof lazy);
        tot=0;
    }
    void addedge(int u,int v){
        edge[tot].to=v;edge[tot].nxt=head[u];head[u]=tot++;
    }
    
    int main(){
        init();
        cin>>n;
        for(int u=2;u<=n;u++){
            int fa;scanf("%d",&fa);fa++;
            addedge(fa,u);addedge(u,fa);
        }
        cnt=0;dfs1(1,0,1);dfs2(1,1);
        
        cin>>q;char op[20];int x;
        while(q--){
            scanf("%s %d",op,&x);++x;
            if(op[0]=='i'){
                int tmp=Query(x,1);
                cout<<d[x]-tmp<<'
    ';
                Set1(x,1); 
            }
            if(op[0]=='u'){
                cout<<query(id[x],id[x]+size[x]-1,1,n,1)<<'
    ';
                set0(id[x],id[x]+size[x]-1,1,n,1);
            }
        }
    }
  • 相关阅读:
    Collection 和 Collections的区别?
    事务是什么?有哪些属性,并简要说明这些属性的含义。
    jsp有哪些内置对象?作用分别是什么?(至少三个)
    谈谈对XML的理解?说明Web应用中Web.xml文件的作用?
    类有哪三个基本特性?各特性的优点?
    Oracle安装完成后,如何用命令行启动和关闭数据库?
    请说明SQLServer中delete from tablea & truncate table tablea的区别
    试述数据库完整保护的主要任务和措施。
    存储过程和函数的区别
    性能
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10757700.html
Copyright © 2020-2023  润新知