https://www.luogu.com.cn/problem/P2420
对于异或,就是将之前的求和的+号改为^ 即可 其他完全一样
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int maxn=200000+10; 5 int n,m,r; 6 //见题意 7 int w[maxn],wt[maxn]; 8 //链式前向星数组,w[]、wt[]初始点权数组 9 int son[maxn],id[maxn],fa[maxn],cnt,dep[maxn],siz[maxn],top[maxn]; 10 //son[]重儿子编号,id[]新编号,fa[]父亲节点,cnt dfs_clock/dfs序,dep[]深度,siz[]子树大小,top[]当前链顶端节点 11 //查询答案 12 struct node 13 { 14 int v,w,nxt; 15 }G[maxn<<2]; int head[maxn]; int num; 16 struct tre 17 { 18 int l,r,lazy,sum; 19 int mx,mn; 20 }tree[maxn<<2]; 21 void add(int u,int v,int w) 22 { 23 G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num; 24 G[++num].v=u;G[num].w=w;G[num].nxt=head[v];head[v]=num; 25 } 26 void build(int l,int r,int root){ 27 tree[root].l=l;tree[root].r=r; 28 tree[root].sum=tree[root].lazy=0; 29 tree[root].mx=-1001; 30 tree[root].mn=1001; 31 if(l==r){ 32 tree[root].sum=wt[l]; 33 tree[root].mn=wt[l]; 34 tree[root].mx=wt[l]; 35 return; 36 } 37 int mid=l+r>>1; 38 build(l,mid,root<<1); 39 build(mid+1,r,root<<1|1); 40 tree[root].sum=tree[root<<1].sum^tree[root<<1|1].sum; 41 } 42 43 int query(int l,int r,int root){ 44 int L=tree[root].l;int R=tree[root].r; 45 if(l<=L&&R<=r){ 46 return tree[root].sum; 47 } 48 int mid=L+R>>1; 49 int ans=0; 50 if(l<=mid) ans^=query(l,r,root<<1); 51 if(r>mid) ans^=query(l,r,root<<1|1); 52 return ans; 53 } 54 55 void dfs1(int u,int f,int deep){//x当前节点,f父亲,deep深度 56 dep[u]=deep;//标记每个点的深度 57 fa[u]=f;//标记每个点的父亲 58 siz[u]=1;//标记每个非叶子节点的子树大小 59 int maxson=-1;//记录重儿子的儿子数 60 for(int i=head[u];i!=-1;i=G[i].nxt){ 61 int v=G[i].v; 62 if(v==f)continue;//若为父亲则continue 63 w[v]=G[i].w; 64 dfs1(v,u,deep+1);//dfs其儿子 65 siz[u]+=siz[v];//把它的儿子数加到它身上 66 if(siz[v]>maxson)son[u]=v,maxson=siz[v];//标记每个非叶子节点的重儿子编号 67 } 68 } 69 70 void dfs2(int u,int topf){//x当前节点,topf当前链的最顶端的节点 71 id[u]=++cnt;//标记每个点的新编号 72 wt[cnt]=w[u];//把每个点的初始值赋到新编号上来 73 top[u]=topf;//这个点所在链的顶端 74 if(!son[u])return;//如果没有儿子则返回 75 dfs2(son[u],topf);//按先处理重儿子,再处理轻儿子的顺序递归处理 76 for(int i=head[u];i!=-1;i=G[i].nxt){ 77 int v=G[i].v; 78 if(v==fa[u]||v==son[u])continue; 79 dfs2(v,v);//对于每一个轻儿子都有一条从它自己开始的链 80 } 81 } 82 int qRange(int x,int y){ 83 int ans=0; 84 while(top[x]!=top[y]){//当两个点不在同一条链上 85 if(dep[top[x]]<dep[top[y]])swap(x,y);//把x点改为所在链顶端的深度更深的那个点 86 ans^=query(id[top[x]],id[x],1);//ans加上x点到x所在链顶端 这一段区间的点权和 87 x=fa[top[x]];//把x跳到x所在链顶端的那个点的上面一个点 88 } 89 //直到两个点处于一条链上 90 if(dep[x]>dep[y])swap(x,y); //把x点深度更深的那个点 91 if(x!=y) 92 ans^=query(id[x]+1,id[y],1); //这时再加上此时两个点的区间和即可 93 return ans; 94 } 95 void init() 96 { 97 memset(head,-1,sizeof(head)); 98 num=-1; 99 } 100 int main(){ 101 init(); 102 int n; 103 scanf("%d",&n); 104 for(int i=1;i<n;i++){ 105 int u,v,w; 106 scanf("%d%d%d",&u,&v,&w); 107 add(u,v,w); 108 } 109 dfs1(1,0,1); 110 dfs2(1,1); 111 build(1,n,1); 112 int T; 113 scanf("%d",&T); 114 while(T--){ 115 int u,v; 116 scanf("%d%d",&u,&v); 117 printf("%d\n",qRange(u,v)); 118 } 119 return 0; 120 }
来源:https://www.cnblogs.com/pangbi/p/12356018.html