• 西安邀请赛-E(树链剖分+线段树)


    题目链接:https://nanti.jisuanke.com/t/39272

    题意:给一棵树,n个结点,树根为1,n-1条边,每个结点有一个权值。进行3种操作:

        1 s t:把1和s之间的最短路径上的所有结点|t。

        2 s t:把1和s之间的最短路径上的所有结点&t。

        3 s t:把1和s之间的最短路径上的所有结点进行异或,若结果等于t则输出NO,否则输出YES。(不理解的话可以看一下nim博弈论)

    思路:很明显的一道题树链剖分题,难的是怎么维护线段树。我们拆成二进制来看,用num[32]维护区间内所有点对应位的1的数量,对于或操作来说,若对应位为1,则区间所有点对应位全改为1,若为0,则不操作; 对于与操作来说,若对应位为0,则区间所有点对应位全为0,若为1,则不操作。而且这两种操作是具有覆盖效果的,那么我们可以用懒惰标记add[i]=1表示该区间第i位全为1,add[i]=-1表示该区间第i位全为0。查询操作时,将查询区间上所有位1的数量模2,即区间异或和的对应位,将其与输入的t比较是否相等即可。

    AC代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int maxn=100005;
    
    int cnt1,head[maxn];
    int dep[maxn],siz[maxn],fa[maxn],son[maxn],top[maxn],cnt2,id[maxn],w[maxn],wt[maxn],res;
    int n,m;
    
    struct node1{
        int v,nex;
    }edge[maxn<<1];
    
    void adde(int u,int v){
        edge[++cnt1].v=v;
        edge[cnt1].nex=head[u];
        head[u]=cnt1;
    }
    
    struct node2{
        int l,r,len;
        int num[32],add[32];
    }tr[maxn<<2];
    
    void pushup(int v){
        for(int i=0;i<30;++i)
            tr[v].num[i]=tr[v<<1].num[i]+tr[v<<1|1].num[i];
    }
    
    void pushdown(int v){
        for(int i=0;i<30;++i){
            if(tr[v].add[i]==1){
                tr[v<<1].num[i]=tr[v<<1].len;
                tr[v<<1].add[i]=1;
                tr[v<<1|1].num[i]=tr[v<<1|1].len;
                tr[v<<1|1].add[i]=1;
                tr[v].add[i]=0;
            }
            if(tr[v].add[i]==-1){
                tr[v<<1].num[i]=0;
                tr[v<<1].add[i]=-1;
                tr[v<<1|1].num[i]=0;
                tr[v<<1|1].add[i]=-1;
                tr[v].add[i]=0;
            }
        }
    }
    
    void build(int v,int l,int r){
        tr[v].l=l,tr[v].r=r,tr[v].len=r-l+1;
        if(l==r){
            for(int i=0;i<30;++i)
                if((1<<i)&wt[r])
                    tr[v].num[i]=1;
            return;
        }
        int mid=(l+r)>>1;
        build(v<<1,l,mid);
        build(v<<1|1,mid+1,r);
        pushup(v);
    }
    
    void update(int v,int l,int r,int op,int k){
        if(l<=tr[v].l&&r>=tr[v].r){
            if(op==1){
                for(int i=0;i<30;++i)
                    if((1<<i)&k){
                        tr[v].num[i]=tr[v].len;
                        tr[v].add[i]=1;
                    }
            }
            else{
                for(int i=0;i<30;++i)
                    if(!((1<<i)&k)){
                        tr[v].num[i]=0;
                        tr[v].add[i]=-1;
                    }
            }
            return;
        }
        pushdown(v);
        int mid=(tr[v].l+tr[v].r)>>1;
        if(l<=mid) update(v<<1,l,r,op,k);
        if(r>mid) update(v<<1|1,l,r,op,k);
        pushup(v);
    }
    
    void query(int v,int l,int r){
        if(l<=tr[v].l&&r>=tr[v].r){
            for(int i=0;i<30;++i){
                if(tr[v].num[i]&1)
                    res^=(1<<i);
            }
            return;
        }
        pushdown(v);
        int mid=(tr[v].l+tr[v].r)>>1;
        if(l<=mid) query(v<<1,l,r);
        if(r>mid) query(v<<1|1,l,r);
    }
    
    void dfs1(int x,int f,int deep){
        fa[x]=f;
        dep[x]=deep;
        siz[x]=1;
        int maxson=-1;
        for(int i=head[x];i;i=edge[i].nex){
            int y=edge[i].v;
            if(y==f) continue;
            dfs1(y,x,deep+1);
            siz[x]+=siz[y];
            if(siz[y]>maxson) son[x]=y,maxson=siz[y];
        }
    }
    
    void dfs2(int x,int tp){
        id[x]=++cnt2;
        wt[cnt2]=w[x];
        top[x]=tp;
        if(!son[x]) return;
        dfs2(son[x],tp);
        for(int i=head[x];i;i=edge[i].nex){
            int y=edge[i].v;
            if(y==fa[x]||y==son[x]) continue;
            dfs2(y,y);
        }
    }
    
    void updRange(int x,int y,int op,int k){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            update(1,id[top[x]],id[x],op,k);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        update(1,id[x],id[y],op,k);
    }
    
    void qRange(int x,int y){
        res=0;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            query(1,id[top[x]],id[x]);
            x=fa[top[x]];        
        }
        if(dep[x]>dep[y]) swap(x,y);
        query(1,id[x],id[y]);
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i)
            scanf("%d",&w[i]);
        for(int i=1;i<n;++i){
            int x,y;
            scanf("%d%d",&x,&y);
            adde(x,y);
            adde(y,x);
        }
        dfs1(1,0,1);
        dfs2(1,1);
        build(1,1,n);
        while(m--){
            int op,s,t;
            scanf("%d%d%d",&op,&s,&t);
            if(op==1||op==2)
                updRange(1,s,op,t);    
            else{
                qRange(1,s);
                if(res==t) printf("NO
    ");
                else printf("YES
    ");
            }
        }
        return 0;
    }

     

  • 相关阅读:
    用jQuery实现的简单柱状统计图
    转:Mac下配置eclipse的pydev
    准备做些东西
    UIImageJPEGRepresentation 和 UIImagePNGRepresentation
    UITableView,UITableViewCell,UIPickerView,UISearchBar
    UITableViewCell的显示格式
    js 数据类型检测
    data-xxx 属性的作用是什么
    TCP连接篇
    DNS篇
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11183377.html
Copyright © 2020-2023  润新知