Title gate: https://www.luogu.org/problemnew/show/P3401
Today is tree planting day. In my spare time in the evening, I saw that minasang was planting the valley tree. I also planted a tree for leisure. As a result, I planted it for 2.5h, and felt that my ability to write data structures had degenerated.
There is a weak version of this topic: gdkoi 2016 magic card girl. That question is to ask the subinterval exclusive or sum of an interval. The method is to separate every bit of binary, and then use line tree to maintain the number of XOR prefixes and 0, 1 in. The answer is to multiply the number and then weight it. The reason for this is that for a contributing interval [L,R], it must be calculated by sum[L-1] and sum[R] only once.
Then this problem only needs to move the problem of sequence to tree chain segmentation, with more details. Here is my mistake:
1. There is no parenthesis in mid when defining
2. bool is misplaced when the line tree recurs to the bottom
3. Forget the influence of light side on XOR sum when jumping heavy chain
4. Forget to initialize the segment tree leaf node when updating
Anyway, 2A.
CODE:
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define mid ((L+R)>>1) //!!!
#define Left (root<<1)
#define Right ((Left)|1)
const int maxk=10;
const int maxn=30010;
typedef long long LL;
struct edge
{
int obj,len;
edge *Next;
} e[maxn<<1];
edge *head[maxn];
int cur=-1;
struct data
{
int sum,num0,num1;
} tree[maxk][maxn<<2];
data zero;
int fa[maxn];
int dep[maxn];
int Son[maxn];
int Size[maxn];
int Top[maxn];
int dfsx[maxn];
int dfn[maxn];
int Time=0;
int val[maxn];
int n,q;
void Add(int x,int y,int z)
{
cur++;
e[cur].obj=y;
e[cur].len=z;
e[cur].Next=head[x];
head[x]=e+cur;
}
void Dfs1(int node)
{
Size[node]=1;
for (edge *p=head[node]; p; p=p->Next)
{
int son=p->obj;
if (son==fa[node]) continue;
fa[son]=node;
val[son]=p->len;
dep[son]=dep[node]+1;
Dfs1(son);
Size[node]+=Size[son];
if (Size[son]>Size[ Son[node] ]) Son[node]=son;
}
}
void Dfs2(int node)
{
dfsx[++Time]=node;
dfn[node]=Time;
if (Son[node]) Top[ Son[node] ]=Top[node],Dfs2(Son[node]);
for (edge *p=head[node]; p; p=p->Next)
{
int son=p->obj;
if ( son==fa[node] || son==Son[node] ) continue;
Top[son]=son;
Dfs2(son);
}
}
data Up(data x,data y)
{
data z;
z.sum=x.sum^y.sum;
if (x.sum) swap(y.num0,y.num1);
z.num0=x.num0+y.num0;
z.num1=x.num1+y.num1;
return z;
}
void Build(int i,int root,int L,int R)
{
if (L==R)
{
int v=((bool)(val[ dfsx[L] ]&(1<<i))); //!!!
tree[i][root].sum=v;
if (v) tree[i][root].num1++;
else tree[i][root].num0++;
return;
}
Build(i,Left,L,mid);
Build(i,Right,mid+1,R);
tree[i][root]=Up(tree[i][Left],tree[i][Right]);
}
int Lca(int u,int v)
{
if (Top[u]==Top[v]) return dfsx[ min(dfn[u],dfn[v]) ];
if (dep[ Top[u] ]<dep[ Top[v] ]) swap(u,v);
return Lca(fa[ Top[u] ],v);
}
data Query(int i,int root,int L,int R,int x,int y)
{
if ( y<L || R<x ) return zero;
if ( x<=L && R<=y ) return tree[i][root];
data vl=Query(i,Left,L,mid,x,y);
data vr=Query(i,Right,mid+1,R,x,y);
return Up(vl,vr);
}
data Get(int i,int u,int v)
{
data x;
if (u==v) x=zero;
else x=Query(i,1,1,n,dfn[v]+1,dfn[u]);
x.num0++;
if (x.sum) swap(x.num0,x.num1);
return x;
}
data Work(int i,int u,int v)
{
if (Top[u]==Top[v]) return Get(i,u,v);
int w=Top[u];
data y=Work(i,fa[w],v);
if (val[w]&(1<<i)) swap(y.num0,y.num1),y.sum^=1; //!!!
data x=Get(i,u,w);
return Up(x,y);
}
LL Ask(int u,int v)
{
int w=Lca(u,v);
LL ans=0;
for (int i=0; i<maxk; i++)
{
data x=Work(i,u,w);
data y=Work(i,v,w);
if (y.sum) swap(y.num0,y.num1);
y.num0--;
x=Up(x,y);
ans+=( (1LL<<i)*(long long)x.num0*(long long)x.num1 );
}
return ans;
}
void Update(int i,int root,int L,int R,int x)
{
if ( L==x && x==R )
{
tree[i][root]=zero; //!!!
int v=((bool)(val[ dfsx[L] ]&(1<<i)));
tree[i][root].sum=v;
if (v) tree[i][root].num1++;
else tree[i][root].num0++;
return;
}
if ( x<L || R<x ) return;
Update(i,Left,L,mid,x);
Update(i,Right,mid+1,R,x);
tree[i][root]=Up(tree[i][Left],tree[i][Right]);
}
int main()
{
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
scanf("%d%d",&n,&q);
for (int i=1; i<=n; i++) head[i]=NULL;
for (int i=1; i<n; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Add(x,y,z);
Add(y,x,z);
}
dep[1]=1;
Dfs1(1);
Top[1]=1;
Dfs2(1);
for (int i=0; i<maxk; i++) Build(i,1,1,n);
zero.sum=zero.num0=zero.num1=0;
while (q--)
{
int x,u,v,w;
scanf("%d%d%d",&x,&u,&v);
if (x==1) printf("%lld\n", Ask(u,v) );
else
{
scanf("%d",&w);
if (fa[u]!=v) swap(u,v);
val[u]=w;
for (int i=0; i<maxk; i++) Update(i,1,1,n,dfn[u]);
}
}
return 0;
}