• hdu 5274 树链剖分


    Dylans loves tree

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 1484    Accepted Submission(s): 347


    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
    /*
    hdu 5274 树链剖分
    
    problem:
    给你有一个树,然后有两个操作
    1.修改第x个节点的值为y
    2.查询x~y路径上哪一个数出现了奇数次
    
    solve:
    由于题目保证只可能有一个数出现奇数次那么求 u->v这条链上所有点权的异或值即可
    以前用 线段树+lca解决的. 这次是直接用的树链剖分,感觉思路都差不多的. 用一个数组映射当前
    节点在线段树上的位置,所以
    1:操作可以直接单点更新解决.
    2:直接查询链上面的异或值就行. 感觉就是让u,v递推到达最小公共祖先,在过程中查询每一条重链or轻链,再将答案和并起来.
    总体上和普通线段树很像
    
    hhh-2016-08-18 15:32:24
    */
    #pragma comment(linker,"/STACK:124000000,124000000")
    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <map>
    #define lson  i<<1
    #define rson  i<<1|1
    #define ll long long
    #define clr(a,b) memset(a,b,sizeof(a))
    #define key_val ch[ch[root][1]][0]
    using namespace std;
    const int maxn = 200100;
    const int inf = 0x3f3f3f3f;
    int head[maxn],tot,pos,son[maxn];
    int top[maxn],fp[maxn],fa[maxn],dep[maxn],num[maxn],p[maxn];
    int n;
    struct Edge
    {
        int to,next;
    } edge[maxn<<1];
    
    void ini()
    {
        tot = 0,pos = 1;
        clr(head,-1),clr(son,-1);
    //    clr(val,0);
    }
    
    void add_edge(int u,int v)
    {
        edge[tot].to = v,edge[tot].next = head[u],head[u] = tot++;
    }
    
    void dfs1(int u,int pre,int d)
    {
        dep[u] = d;
        fa[u] = pre,num[u] = 1;
    //    cout << "node:" << u<<endl;
        for(int i = head[u]; ~i; i = edge[i].next)
        {
            int v = edge[i].to;
            if(v != pre)
            {
                dfs1(v,u,d+1);
                num[u] += num[v];
                if(son[u] == -1 || num[v] > num[son[u]])
                    son[u] = v;
            }
        }
    }
    
    void getpos(int u,int sp)
    {
        top[u] = sp;
        p[u] = pos++;
        fp[p[u]] = u;
        if(son[u] == -1)return ;
        getpos(son[u],sp);
        for(int i = head[u]; ~i ; i = edge[i].next)
        {
            int v = edge[i].to;
            if(v != son[u] && v != fa[u])
                getpos(v,v);
        }
    }
    
    struct node
    {
        int l,r,mid;
        ll Min;
    } tree[maxn << 2];
    void push_up(int i)
    {
        tree[i].Min = tree[lson].Min^tree[rson].Min;
    }
    void build(int i,int l,int r)
    {
        tree[i].l = l,tree[i].r = r;
        tree[i].Min = inf;
        tree[i].mid=(l+r) >>1;
        if(l == r)
        {
    //        cout << fp[l] <<" " <<val[fp[l]]<<endl;
            return;
        }
        build(lson,l,tree[i].mid);
        build(rson,tree[i].mid+1,r);
    }
    
    void update(int i,int k,int val)
    {
        if(tree[i].l == k && tree[i].r == k)
        {
    //        cout << fp[k] <<" " <<val<<endl;
            tree[i].Min = val;
            return;
        }
        int mid = tree[i].mid;
        if(k <= mid) update(lson,k,val);
        else update(rson,k,val);
        push_up(i);
    //    cout << tree[i].l <<" " <<tree[i].r <<" " <<tree[i].Min<<endl;
    }
    ll query(int i,int l,int r)
    {
    //    cout <<"l:"<< l <<" r:"<<r <<" min:"<< tree[i].Min<<endl;
        if(tree[i].l >= l && tree[i].r <= r)
            return tree[i].Min;
        int mid = tree[i].mid;
        if(r <= mid)
            return query(lson,l,r);
        else if(l > mid)
            return query(rson,l,r);
        else
        {
            return query(lson,l,mid)^query(rson,mid+1,r);
        }
    }
    ll fin(int u,int v)
    {
        int f1 = top[u],f2 = top[v];
        ll tmp = 0;
    //     cout <<u <<" " <<v <<endl;
    //   cout <<f1 <<" " <<f2 <<endl;
        while(f1 != f2)
        {
            if(dep[f1] < dep[f2])
            {
                swap(f1,f2),swap(u,v);
            }
            tmp = tmp^query(1,p[f1],p[u]);
            u = fa[f1],f1 = top[u];
        }
        if(u == v) return tmp;
        if(dep[u] > dep[v]) swap(u,v);
    //    cout << son[u] << " " <<v <<endl;
        return (tmp^query(1,p[u],p[v]));
    }
    
    //int a[maxn];
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        int T,cas = 1,op;
        int a,b;
        int m,u,v;
        scanf("%d",&T);
        while(T--)
        {
           ini();
           scanf("%d%d",&n,&m);
           for(int i =1;i <n;i++)
           {
               scanf("%d%d",&u,&v);
               add_edge(u,v);
               add_edge(v,u);
           }
           dfs1(1,0,0);
           getpos(1,1);
           build(1,1,pos-1);
           for(int i =1;i <= n;i++)
           {
               scanf("%d",&a);
               update(1,p[i],a+1);
           }
           for(int i = 1;i <= m;i++)
           {
               scanf("%d%d%d",&op,&a,&b);
               if(op == 0)
               {
                   update(1,p[a],b+1);
               }
               else
               {
                   int t = fin(a,b);
    //               cout<<"t:"<<t<<endl;
                   if(!t)
                    printf("-1
    ");
                   else
                    printf("%d
    ",t-1);
               }
           }
        }
        return 0;
    }
    

      

  • 相关阅读:
    Linux查看文件夹大小
    mysql按照天或小时group分组统计
    eclipse可以调试但是无法打开网页,提示一直在加载
    自定义spring valid方式实现验证
    UniCode编码表及部分不可见字符过滤方案
    shiro中移除jsessionid的解决方案
    Apache Shiro去掉URL中的JSESSIONID
    shiro开启realm
    shiro注解@RequiresPermissions多权限任选一参数用法
    linux 复制粘贴
  • 原文地址:https://www.cnblogs.com/Przz/p/5792193.html
Copyright © 2020-2023  润新知