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