BestCoder #45 1003 Dylans loves tree

来源:互联网 发布:创维网络电视50价格 编辑:程序博客网 时间:2024/05/16 11:55

problem


题意

  • 给定一棵树,并给定在这棵树上的两种操作。一种操作是改变一个节点的权值,另外一个操作是对两个节点之间的路径上的权值进行统计,如果每个权值出现的次数都是偶数,输出-1,否则输出出现次数为奇数的权值(保证只有一个)

思路

  • 这题是一个DFS序的模板题。首先想到,我们获得这棵树的DFS序,对于这个序列,我们可以去维护区间的异或和。由于是单点修改区间查询,可以用树状数组也可以直接写线段树。然后对于每个询问,我们查询出每个点到根的异或和(这里直接用DFS序中到根节点的异或和即可,因为如果一个结点不在其到根节点的路径上,其会出现两次,异或和为0),然后求出这两个结点的LCA,再异或LCA的权值。注意这个地方,如果一个结点权值为0,会出错。所以这里要进行处理(把权值都加1,输出答案的时候减1)。LCA用倍增法、Tarjan、RMQ都可以。
  • 这题HDU略坑,交G++一直爆栈。然而没必要去管这个。。交C++就过了。
  • 利用了G++开栈的代码,成功在G++下AC。。

AC代码

g++开栈代码

register char *_sp __asm__("rsp");int main(){    const int size = 64*1024*1024;    static char *sys,*mine(new char[size]+size-4096);    sys = _sp;_sp = mine;mmain();_sp = sys;    return 0;}
#include <iostream>#include <cstdio>#include <vector>#include <algorithm>#include <cstring>#include <cmath>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int MAXN = 110000;int cnt,head[MAXN],dep[MAXN],p[MAXN][20],tot;int st[MAXN],ed[MAXN];int sum[MAXN<<3];int n,q;void update(int pos,int c,int l,int r,int rt){    if(l == r){        sum[rt] = c;        return;    }    int m = (l+r)>>1;    if(pos <= m)update(pos,c,lson);    else update(pos,c,rson);    sum[rt] = sum[rt<<1] ^ sum[rt<<1|1];}int query(int L,int R,int l,int r,int rt){    if(l>=L && R>=r){        return sum[rt];    }    int ret = 0;    int m = (l+r)>>1;    if(L <= m)ret ^= query(L,R,lson);    if(R > m)ret ^= query(L,R,rson);    return ret;}struct Edge{    int u,v;    int next;}e[MAXN<<1];void addedge(int u,int v){    e[cnt].u = u,e[cnt].v = v,e[cnt].next = head[u],head[u] = cnt++;    e[cnt].u = v,e[cnt].v = u,e[cnt].next = head[v],head[v] = cnt++;}void dfs(int u){    st[u] = tot++;    for(int i=head[u];i!=-1;i=e[i].next){        int v = e[i].v;        if(!dep[v]){            dep[v] = dep[u] + 1;            p[v][0] = u;            dfs(v);        }    }    ed[u] = tot++;}void init(){    cnt = 0;    tot = 1;    memset(head,-1,sizeof(head));    memset(p,-1,sizeof(p));    memset(dep,0,sizeof(dep));}int LCA(int a,int b){    if(dep[a]<dep[b])swap(a,b);    int i;    for(i = 0;(1<<i)<=dep[a];i++);    i--;    for(int j=i;j>=0;j--)        if(dep[a]-(1<<j)>=dep[b])            a = p[a][j];    if(a == b)return a;    for(int j=i;j>=0;j--){        if(p[a][j]!=-1 && p[a][j] != p[b][j]){            a = p[a][j];            b = p[b][j];        }    }    return p[a][0];}int u,v;int main(){    int T;    cin>>T;    while(T--){        scanf("%d%d",&n,&q);        init();        for(int i=0;i<n-1;i++){            scanf("%d%d",&u,&v);            addedge(u,v);        }        dep[1] = 1;        dfs(1);        for(int j=1;(1<<j)<=n;j++)            for(int i=1;i<=n;i++)                if(p[i][j-1] != -1)                    p[i][j] = p[p[i][j-1]][j-1];        tot--;        memset(sum,0,sizeof(sum));        //for(int i=1;i<=n;i++)printf("%d ",st[i]);        //printf("tot : %d\n",tot);        for(int i=1;i<=n;i++){            scanf("%d",&u);            update(st[i],u+1,1,tot,1),update(ed[i],u+1,1,tot,1);        }        while(q--){            int op,x,y;            scanf("%d%d%d",&op,&x,&y);            if(op == 0){                update(st[x],y+1,1,tot,1),update(ed[x],y+1,1,tot,1);            }else{                int ansx = query(1,st[x],1,tot,1),ansy = query(1,st[y],1,tot,1);                int lca = LCA(x,y),anslca =query(st[lca],st[lca],1,tot,1);                //printf("ansx:%d ansy:%d lca:%d\n",ansx,ansy,lca);                int ans = ansx ^ ansy ^ anslca;                if( ans == 0)puts("-1");                else printf("%d\n",ans-1);            }        }    }    return 0;}
0 0
原创粉丝点击