• 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)


    题目

    传送门:QWQ

    分析

     先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug、手写栈)

    然后去学了学正解

    核心挺好理解的,$ query(a) $是$ a $到根的异或和。

    答案就是$ lca(x,y) hat{}  query(x)  hat{}  query(b) $

    接着维护异或和,很显然线段树挺容易搞的。

    但我们今天学学树状数组来维护异或和

    若将区间$ [l,r] $内的元素全部异或x,相当于在第l位标记x,再在第r+1位标记x,
    这样,对于第r位以后的元素,这两个命令互相抵消,查询某个元素的值,只需用树状数组把它之前的命令全部累加起来即可。

    强无敌了~~~ 

    代码

    lca+dfs序+树状数组:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=500005;
    int fa[maxn][20],depth[maxn],w[maxn];
    int in[maxn],out[maxn],cnt,vis[maxn],n,bit[maxn];
    vector<int> G[maxn];
    int dfs(int u){
        for(int i=1;i<19;i++){
            if(depth[u] < (1 << i)) break;
            fa[u][i]=fa[fa[u][i-1]][i-1];
        }
        in[u]=++cnt;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i]; if(vis[v]) continue; vis[v]=1; 
            fa[v][0]=u; depth[v]=depth[u]+1; dfs(v);
        } out[u]=cnt;
    }
    int lca(int x,int y){
        if(depth[x]<depth[y]) swap(x,y);
        int d=(depth[x]-depth[y]);
        for(int i=0;i<19;i++){ 
            if((1<<i) & d) x=fa[x][i];
        }
        for(int i=18;i>=0;i--){
            if(fa[x][i]!=fa[y][i]){
                x=fa[x][i]; y=fa[y][i];
            }
        }
        if(x==y) return x;
        else return fa[x][0];
    }
    void add(int x,int v){for(;x<=n;x+=x&-x) bit[x]^=v;}
    int query(int x){int ans=0;for(;x>0;x-=x&-x) ans^=bit[x];return ans;} 
    int main()
    {
        int u,v,q;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&w[i]);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            G[u].push_back(v);G[v].push_back(u);
        }
        vis[1]=1;dfs(1);
        for(int i=1;i<=n;i++){
            add(in[i],w[i]); add(out[i]+1,w[i]);
        }
        scanf("%d",&q);
        int a,b; char s[10];
        while(q--){
            scanf("%s%d%d",s,&a,&b);
            if(s[0]=='Q'){
                int ans=w[lca(a,b)]^query(in[a])^query(in[b]);
                if(ans!=0) puts("Yes");
                else puts("No");
            //    printf("---------------   %d %d %d
    ",lca(a,b),query(in[a]),query(in[b]));
            }
            else{
                add(in[a],w[a]);add(out[a]+1,w[a]);
                w[a]=b;
                add(in[a],w[a]);add(out[a]+1,w[a]);
            }
        }
        return 0;
    }
    /*
    8
    1 3 5 2 5 3 1 1
    1 5
    3 5
    2 5
    1 4
    6 3
    7 4
    8 3
    13
    Q 1 2
    Q 3 5
    Q 1 8
    Q 3 5
    Q 6 2
    C 2 5
    C 4 6
    C 8 5
    Q 1 2
    Q 3 5
    Q 1 8
    Q 3 5
    Q 6 2
    */ 

    树链剖分(无法AC):

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=500005;
    int top[maxn],fa[maxn],son[maxn],dep[maxn],siz[maxn];
    int wt[2*maxn],w[2*maxn],id[2*maxn],v[2*maxn],cnt,n;
    vector<int> G[maxn];
    void build(int o,int l,int r){
        if(l==r){ v[o]=wt[l]; return; }
        int mid=l+r>>1;
        build(o<<1,l,mid); build(o<<1|1,mid+1,r);
        v[o]=v[o<<1]^v[o<<1|1];
    } 
    void update(int o,int l,int r,int val,int L){    
    //    printf("--->>>  %d %d %d %d %d
    ",o,l,r,val,L);
        if(l==r){
            v[o]=val; return;
        }
        int mid=l+r>>1; 
        if(L<=mid) update(o<<1,l,mid,val,L); 
        else update(o<<1|1,mid+1,r,val,L);
        v[o]=v[o<<1]^v[o<<1|1];
    }
    int query(int o,int l,int r,int L,int R){
        if(l>R||r<L) return 0;
        if(l>=L&&r<=R){return v[o];}
        int mid=l+r>>1;
        int ans=query(o<<1,l,mid,L,R)^query(o<<1|1,mid+1,r,L,R);
        return ans;
    } 
    ///////////////////////////////////////////
    int dfs1(int x,int f,int depth){
        dep[x]=depth; fa[x]=f; siz[x]=1;
        int maxnum=0;
        for(int i=0;i<G[x].size();i++){
            int v=G[x][i];
            if(v==f) continue;
            dfs1(v,x,depth+1);
            siz[x]+=siz[v];
            if(maxnum<siz[v]){
                maxnum=siz[v]; son[x]=v;
            }
        }
    }
    void dfs2(int x,int topf){
        top[x]=topf; id[x]=++cnt; wt[id[x]]=w[x];
        if(!son[x]) return;
        dfs2(son[x],topf);
        for(int i=0;i<G[x].size();i++){
            int v=G[x][i];
            if(v!=son[x]&&v!=fa[x]){
                dfs2(v,v);
            }
        }
    }
    void debug(){
        puts("
    depth: ");
        for(int i=1;i<=n;i++) printf("%d ",dep[i]);
        puts("
    son: ");
        for(int i=1;i<=n;i++) printf("%d ",son[i]);
        puts("
    top: ");
        for(int i=1;i<=n;i++) printf("%d ",top[i]);
    }
    int Qu(int x,int y){
        int ans=0;
        for(;top[x]!=top[y];){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ans^=query(1,1,n,id[top[x]],id[x]);
            x=fa[top[x]]; 
        }
        if(dep[x]>dep[y]) swap(x,y);
        ans^=query(1,1,n,id[x],id[y]);
        return ans;
    } 
    int main()
    {
    //    freopen("1.txt","r",stdin);
        
    //    int __size__=30<<20;  
    //    char *__p__=(char*)malloc(__size__)+__size__;  
    //    __asm__("movl %0, %%esp
    "::"r"(__p__));
        int u,v,q;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&w[i]);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            G[u].push_back(v);G[v].push_back(u);
        }
        dfs1(1,0,1); dfs2(1,1);
        build(1,1,n);
        scanf("%d",&q);
    //    printf("======   %d
    ",query(1,1,n,1,1));
        int a,b; char s[10];
        while(q--){
        //    printf("=========  %d
    ",q);
            scanf("%s%d%d",s,&a,&b);
            if(s[0]=='Q'){
                int ans=Qu(a,b);
                if(ans!=0) puts("Yes");
                else puts("No");
            }
            else{
                update(1,1,n,b,id[a]);
            }
        }
    //    debug();
        return 0;
    }
    /*
    8
    1 3 5 2 5 3 1 1
    1 5
    3 5
    2 5
    1 4
    6 3
    7 4
    8 3
    13
    Q 1 2
    Q 3 5
    Q 1 8
    Q 3 5
    Q 6 2
    C 2 5
    C 4 6
    C 8 5
    Q 1 2
    Q 3 5
    Q 1 8
    Q 3 5
    Q 6 2
    */ 
  • 相关阅读:
    准备活动
    几个很好的.Net开源框架
    windows 进程通信(使用DDE)(转)
    mysql error 1046 1064 1264 (ERROR大全)
    在版本库里建立版本
    20120206系统日志
    Cocos2dx项目从VS移植到Xcode中的配置
    用python解析JSON
    win10下vc++6.0的安装问题
    Python爬虫(一)抓取指定的页面
  • 原文地址:https://www.cnblogs.com/noblex/p/9136837.html
Copyright © 2020-2023  润新知