hdu5274 Dylans loves tree LCA+线段树

来源:互联网 发布:淘宝客可以注销吗 编辑:程序博客网 时间:2024/05/16 19:20

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5274
在树上的询问和操作,每次修改单点值,询问两点之间出现次数为奇数的点权是什么,若没有输出-1.询问保证两点间至多只有一个数出现奇数次。

有一种经典的将树上的点转化成序列的方法,我们用dfs遍历这棵树,那么对于一个节点,他一点比他的子树即子节点先访问到,且当他的最后一个子节点的所有子树也都访问完时,这中间访问的节点一定都是他的子树。那么我们可以在访问时做一下记录,每个点首先被访问的clock,和结束时的clock,那么这中间的便是他的子树。

剩下的就可以用线段树维护区间异或和了。
这题有坑的地方就是点权可能为0,处理方法是先把所以的点权都加上1,最后再减1.

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<vector>#include<set>#define Lson Ls,L,mid#define Rson Rs,mid+1,Rusing namespace std;typedef long long ll;const int N = 2*1e5+10;const int maxh = 20;vector<int> g[N];int anc[N][maxh];int n,q,u,v,clock;int st[N],ed[N],deep[N];int val[N];void dfs(int x,int pa,int de){    deep[x] = de;    st[x] =  ++clock;    anc[x][0] = pa;    for(int i=0;i<g[x].size();i++)if(g[x][i]!=pa){        dfs(g[x][i],x,de+1);    }    ed[x] = clock;}void init_lca(){    dfs(1,-1,0);    for(int k=0;k<maxh-1;k++){        for(int i=1;i<=n;i++)            if(anc[i][k]<0) anc[i][k+1] = -1;            else anc[i][k+1] = anc[anc[i][k]][k];    }}int swim(int x, int H){    for(int i = 0; H; i++){        if (H&1) x = anc[x][i];        H >>= 1;    }    return x;}int lca(int u,int v){    if(deep[u]>deep[v]) swap(u,v);    int H = deep[v]-deep[u];    v = swim(v,H);    if(u==v) return u;    for(int k=maxh-1;k>=0;k--)        if(anc[u][k]!=anc[v][k]){            u = anc[u][k];            v = anc[v][k];        }    return anc[u][0];}struct Node{    int val, set;}tree[N<<2];inline void update(Node& fa, Node& Ls, Node& Rs){    fa.val = (Ls.val ^ Rs.val);}inline void pushdown(Node& fa, Node& Ls, Node& Rs){    if (fa.set != 0){        Ls.val ^= fa.set; Ls.set ^= fa.set;        Rs.val ^= fa.set; Rs.set ^= fa.set;        fa.set = 0;    }}void insert(int v, int L, int R, int p, int q, int delta){    if (p<=L && R<=q){        tree[v].val ^= delta;        tree[v].set ^= delta;        return;    }    int Ls = v<<1, Rs = Ls+1, mid = (L+R)/2;    pushdown(tree[v], tree[Ls], tree[Rs]);    if (q<=mid) insert(Lson, p, q, delta);    else if (p>mid) insert(Rson, p, q, delta);    else{        insert(Lson, p, q, delta);        insert(Rson, p, q, delta);    }    update(tree[v], tree[Ls], tree[Rs]);}int query(int v, int L, int R,int ql, int qr){    if(ql<=L && R<=qr){        return tree[v].val;    }    int Ls = v<<1, Rs = Ls+1, mid = (L+R)/2;    pushdown(tree[v], tree[Ls], tree[Rs]);    int ans = 0;    if(qr<=mid) ans ^= query(Lson,ql,qr);    else if(ql>mid) ans ^= query(Rson,ql,qr);    else{        ans ^= query(Lson,ql,qr);        ans ^= query(Rson,ql,qr);    }    return ans ;}int MAIN(){    int T;    cin >> T;    while(T--){        clock = 0;        scanf("%d%d",&n,&q);        for(int i=1;i<=n;i++) g[i].clear();        for(int i=1;i<=n-1;i++){            scanf("%d%d",&u,&v);            g[u].push_back(v);            g[v].push_back(u);        }        for(int i=1;i<=n;i++){            scanf("%d",&val[i]);            val[i]++;        }        init_lca();        memset(tree,0,sizeof(tree));        for(int i=1;i<=n;i++)            insert(1,1,n,st[i],ed[i],val[i]);        for(int i=1;i<=q;i++){            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            if(a==0){                c++;                insert(1,1,n,st[b],ed[b],val[b]^c);                val[b] = c;            }            else{                int wt1 = query(1,1,n,st[b],st[b]);                int wt2 = query(1,1,n,st[c],st[c]);                int hc = lca(b,c);                int wt3 = val[hc];                int ans = wt1^wt2^wt3;                printf("%d\n",ans-1);            }        }    }    return 0;}const int main_stack = 16;char my_stack[128<<20];int main() {    __asm__("movl %%esp, (%%eax);\n"::"a"(my_stack):"memory");    __asm__("movl %%eax, %%esp;\n"::"a"(my_stack + sizeof(my_stack) - main_stack):"%esp");    MAIN();    __asm__("movl (%%eax), %%esp;\n"::"a"(my_stack):"%esp");    return 0;}
0 0
原创粉丝点击