zoukankan      html  css  js  c++  java
  • HDU 5274 Dylans loves tree(LCA+dfs时间戳+成段更新 OR 树链剖分+单点更新)

    Problem Description
    Dylans is given a tree with N nodes.

    All nodes have a value A[i].Nodes on tree is numbered by 1N.

    Then he is given Q questions like that:

    0 x y:change node xs value to y

    1 x y:For all the value in the path from x to y,do they all appear even times?

    For each ② question,it guarantees that there is at most one value that appears odd times on the path.

    1N,Q100000, the value A[i]N and A[i]100000
     

    Input
    In the first line there is a test number T.
    (T3 and there is at most one testcase that N>1000)

    For each testcase:

    In the first line there are two numbers N and Q.

    Then in the next N1 lines there are pairs of (X,Y) that stand for a road from x to y.

    Then in the next line there are N numbers A1..AN stand for value.

    In the next Q lines there are three numbers(opt,x,y).
     

    Output
    For each question ② in each testcase,if the value all appear even times output "-1",otherwise output the value that appears odd times.
     

    Sample Input
    1 3 2 1 2 2 3 1 1 1 1 1 2 1 1 3
     

    Sample Output
    -1 1
    Hint
    If you want to hack someone,N and Q in your testdata must smaller than 10000,and you shouldn't print any space in each end of the line.
     

    Source
     


    大致题意:

    一棵树1e5节点的树。有1e5次两种操作。改动某点的权值,询问两点间的路径上的每一个权值是否都是偶数个,若不是输出奇数个的权值大小。保证询问的路径上最多仅仅有一个权值是奇数个


    思路:

    方法1.维护每一个点到根的异或,然后查询就是xor[u]^xor[v]^LCA(u,v)

    更新操作:更新某个点显然此点的子树的xor到根的异或都会更新。所以用dfs记录进入节点和退出节点的时间戳,把时间戳作为节点映射到线段树上(所以个数是数节点的两倍),然后成段更新进入此节点到退出此节点的时间戳的区间就可以

    复杂度是nlogn

    方法2:

    正面上。询问就是两个点间的路径的异或,即树链剖分

    复杂度n*logn*logn


    方法一:

    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <sstream>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <ctime>
    #include <bitset>
    #include <algorithm>
    #define SZ(x) ((int)(x).size())
    #define ALL(v) (v).begin(), (v).end()
    #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
    #define REP(i,n) for ( int i=1; i<=int(n); i++ )
    using namespace std;
    typedef long long ll;
    
    const int N = 1e5+100;
    int n,Q;
    int indx;
    struct Edge
    {
        int v,nxt;
        Edge(){}
        Edge(int v,int nxt):v(v),nxt(nxt){}
    }es[N<<1];
    int head[N],ecnt;
    inline void add_edge(int v,int u)
    {
        es[ecnt] = Edge(v,head[u]);
        head[u] = ecnt++;
        es[ecnt] = Edge(u,head[v]);
        head[v] = ecnt++;
    }
    int val[N];
    //....................................
    #define root 1,indx,1
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    int XOR[N<<2];
    inline void pushup(int rt)
    {
        XOR[rt] = XOR[rt<<1]^XOR[rt<<1|1];
    }
    void update(int pos,int x,int l,int r,int rt)
    {
        if(l == r)
        {
            XOR[rt] ^= x;
            return ;
        }
        int m = (l+r)>>1;
        if(pos <= m) update(pos,x,lson);
        else update(pos,x,rson);
        pushup(rt);
    }
    int query(int L,int R,int l,int r,int rt)
    {
        if(L <= l && r <= R) return XOR[rt];
        int m = (l+r)>>1;
        int ans = 0;
        if(L <= m) ans ^= query(L,R,lson);
        if(R > m) ans ^= query(L,R,rson);
        return ans;
    }
    //.................................
    int dep[N],hvyson[N],sz[N],fa[N];
    void dfs1(int u)
    {
        dep[u] = dep[fa[u]]+1;
        hvyson[u] = 0,sz[u] = 1;
        for(int i = head[u];~i;i = es[i].nxt)
        {
            int v = es[i].v;
            if(v == fa[u]) continue;
            fa[v] = u;
            dfs1(v);
            sz[u] += sz[v];
            if(sz[v] > sz[hvyson[u]]) hvyson[u] = v;
        }
    }
    int tp[N],tid[N];
    void dfs2(int u,int ance)
    {
        tid[u] = ++indx;
        tp[u] = ance;
        if(hvyson[u]) dfs2(hvyson[u],ance);
        for(int i = head[u];~i;i = es[i].nxt)
        {
            int v = es[i].v;
            if(v == fa[u]) continue;
            if(v != hvyson[u])dfs2(v,v);
        }
    }
    int ask(int u,int v)
    {
        int anceu = tp[u],ancev = tp[v];
        int ans = 0;
        while(anceu != ancev)
        {
            if(dep[anceu] < dep[ancev]) swap(anceu,ancev),swap(u,v);
            ans ^= query(tid[anceu],tid[u],root);
            u = fa[anceu];
            anceu = tp[u];
        }
        if(u == v) return ans ^= val[u];
        if(dep[u] < dep[v]) return ans ^= query(tid[u],tid[v],root);
        else return ans ^= query(tid[v],tid[u],root);
    }
    //..................................
    void ini()
    {
        ecnt = indx = 0;
        memset(head,-1,sizeof(head));
        memset(XOR,0,sizeof(XOR));
    }
    int main()
    {
    
        int T;
        scanf("%d",&T);
        while(T--)
        {
            ini();
            scanf("%d%d",&n,&Q);
            REP(i,n-1)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                add_edge(u,v);
            }
            REP(i,n) scanf("%d",&val[i]),val[i]++;
            dfs1(1);
            dfs2(1,1);
            REP(i,n) update(tid[i],val[i],root);
            REP(i,Q)
            {
                int op;
                scanf("%d",&op);
                if(op == 0)
                {
                    int u,x;
                    scanf("%d%d",&u,&x);x++;
                    update(tid[u],val[u]^x,root);
                    val[u] = x;
                }
                else
                {
                    int u,v;
                    scanf("%d%d",&u,&v);
                    printf("%d
    ",ask(u,v)-1);
                }
            }
        }
    }


    方法二:

    //312MS 21660K 4306 B C++
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <queue>
    #include <stack>
    #include <list>
    #include <map>
    #include <set>
    #include <sstream>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <ctime>
    #include <bitset>
    #include <algorithm>
    #define SZ(x) ((int)(x).size())
    #define ALL(v) (v).begin(), (v).end()
    #define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
    #define REP(i,n) for ( int i=1; i<=int(n); i++ )
    using namespace std;
    typedef long long ll;
    
    const int N = 1e5+100;
    int n,Q;
    struct Edge
    {
        int v,nxt;
        Edge(){}
        Edge(int v,int nxt) : v(v),nxt(nxt){}
    }es[N*2];
    int ecnt,head[N];
    inline void add_edge(int u,int v)
    {
        es[ecnt] = Edge(v,head[u]);
        head[u] = ecnt++;
        es[ecnt] = Edge(u,head[v]);
        head[v] = ecnt++;
    }
    int val[N];
    //...................................
    
    int indx,st[N],ed[N],vs[N<<1];
    int dp[N];
    void dfs(int u,int fa)
    {
        dp[u] = dp[fa]^val[u];
        st[u] = ++indx;
        vs[indx] = u;
        for(int i = head[u];~i;i = es[i].nxt)
        {
            int v = es[i].v;
            if(v == fa) continue;
            dfs(v,u);
        }
        ed[u] = ++indx;
        vs[indx] = u;
    }
    
    
    //...............................
    
    int dep[N];
    bool vis[N];
    int pa[N][20];
    void bfs()
    {
        queue<int>q;
        q.push(1);
        pa[1][0]=1;
        vis[1]=1;
        while(!q.empty())
        {
            int u=q.front(); q.pop();
            for(int i=1;i<20;i++) pa[u][i]=pa[pa[u][i-1]][i-1];
            for(int i=head[u];~i;i=es[i].nxt)
            {
                int v=es[i].v;
                if(vis[v]==0)
                {
                    vis[v]=1;
                    pa[v][0]=u;
                    dep[v]=dep[u]+1;
                    q.push(v);
                }
            }
        }
    }
    
    int LCA(int u,int v)
    {
        if(dep[u]>dep[v]) swap(u,v);
        for(int det=dep[v]-dep[u],i=0;det;i++,det>>=1)
            if(det&1) v=pa[v][i];
        if(v==u) return v;
        for(int i=20-1;i>=0;i--)
            if(pa[u][i]!=pa[v][i]) v=pa[v][i],u=pa[u][i];
        return pa[u][0];
    }
    //...............................
    int XOR[(N<<1)<<2],col[(N<<1)<<2];
    #define root 1,indx,1
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    inline void pushup(int rt)
    {
        XOR[rt] = XOR[rt<<1]^XOR[rt<<1|1];
    }
    inline void pushdown(int rt)
    {
        if(col[rt] == 0) return ;
        col[rt<<1] ^= col[rt];
        col[rt<<1|1] ^= col[rt];
        XOR[rt<<1] ^= col[rt];
        XOR[rt<<1|1] ^= col[rt];
        col[rt] = 0;
    }
    void build(int l,int r,int rt)
    {
        if(l == r)
        {
            XOR[rt] = dp[vs[l]];
            col[rt] = 0;
            return ;
        }
        int m = (l+r)>>1;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(int L,int R,int x,int l,int r,int rt)
    {
        if(L <= l && r <= R)
        {
            XOR[rt] ^= x;
            col[rt] ^= x;
            return ;
        }
        pushdown(rt);
        int m = (l+r)>>1;
        if(L <= m) update(L,R,x,lson);
        if(R > m) update(L,R,x,rson);
        pushup(rt);
    }
    int query(int pos,int l,int r,int rt)
    {
        if(l == r) return XOR[rt];
        pushdown(rt);
        int m = (l+r)>>1;
        if(pos <= m) return query(pos,lson);
        else return query(pos,rson);
    }
    //..............................
    void ini()
    {
        indx = ecnt = 0;
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            ini();
            scanf("%d%d",&n,&Q);
            REP(i,n-1)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                add_edge(u,v);
            }
            REP(i,n) scanf("%d",&val[i]),val[i]++;
            dfs(1,0);
            bfs();
            build(root);
            while(Q--)
            {
                int op;
                scanf("%d",&op);
                if(op == 0)
                {
                    int u,x;
                    scanf("%d%d",&u,&x);
                    x++;
                    update(st[u],ed[u],val[u]^x,root);
                    val[u] = x;
                }
                else
                {
                    int u,v;
                    scanf("%d%d",&u,&v);
                    int ans = query(ed[u],root)^query(ed[v],root)^val[LCA(u,v)];
                    printf("%d
    ",ans-1);
                }
            }
        }
    }
    



  • 相关阅读:
    SqlSession接口和Executor
    MySQL 存储表情字符
    Lisp学习--Windows下面的开发环境搭建
    使用反射+缓存+委托,实现一个不同对象之间同名同类型属性值的快速拷贝
    GIT团队合作探讨之一-保持工作同步的概念和实践
    关于IE8下media query兼容的解决方案探讨
    git下的团队合作模型及git基础知识汇集
    互联网环境下服务提供的模式
    web统计数据搜集及分析原理
    网站统计及移动应用数据统计相关术语知识详解
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6811754.html
Copyright © 2011-2022 走看看