題面
題意:一棵樹,支持邊修改,問路徑的子路徑異或和。
異或運算每位獨立
gdkoi魔卡燒酒Sakura的套路
區間的子區間的異或和爲區間異或前綴和 中0的個數乘1的個數
因爲在前綴和中的0和1可以任意配對,也只有01配對能產生貢獻
用線段樹維護這個就行了
根據Kscla的掃盲教育
長爲len的區間有len+1個異或前綴和
若區間的異或和爲0,則前綴和0/1的個數和後綴和0/1的個數相等
否則交換0/1的個數即可
所以只要維護1的個數和區間異或和就行了
額,還有噁心的樹鏈剖分
#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))
typedef long long LL;
const int N=100100;
void read(int &hy)
{
hy=0;
char cc=getchar();
while(cc<'0'||cc>'9')
cc=getchar();
while(cc>='0'&&cc<='9')
{
hy=(hy<<3)+(hy<<1)+cc-'0';
cc=getchar();
}
}
int n,q;
int to[N],nex[N],val[N],head[N],cnt;
int dfn[N],dep[N],son[N],siz[N],a[N],w[N],fa[N],top[N],times;
struct yy
{
int t[10],s[10],len;
}f[N<<2],tu;
void add(int u,int v,int va)
{
to[++cnt]=v;
val[cnt]=va;
nex[cnt]=head[u];
head[u]=cnt;
}
void dfs(int x)
{
siz[x]=1;
for(int h=head[x];h;h=nex[h])
if(!siz[to[h]])
{
a[to[h]]=val[h];
fa[to[h]]=x;
dep[to[h]]=dep[x]+1;
dfs(to[h]);
siz[x]+=siz[to[h]];
if(siz[to[h]]>siz[son[x]])
son[x]=to[h];
}
}
void dfs2(int x,int tp)
{
dfn[x]=++times;
w[times]=a[x];
top[x]=tp;
if(son[x])
dfs2(son[x],tp);
for(int h=head[x];h;h=nex[h])
if(to[h]!=fa[x]&&to[h]!=son[x])
dfs2(to[h],to[h]);
}
yy rev(yy x)
{
yy hy=x;
for(int i=0;i<=9;i++)
if(x.t[i])
hy.s[i]=x.len+1-x.s[i];
return hy;
}
yy up(yy L,yy R)
{
yy hy;
for(int i=0;i<=9;i++)
{
if(L.t[i])
hy.s[i]=L.s[i]+R.len-R.s[i];
else
hy.s[i]=L.s[i]+R.s[i];
hy.t[i]=L.t[i]^R.t[i];
}
hy.len=L.len+R.len;
return hy;
}
void build(int ro,int l,int r)
{
if(l==r)
{
for(int i=0;i<=9;i++)
if(w[l]&(1<<i))
f[ro].s[i]=f[ro].t[i]=1;
f[ro].len=1;
return;
}
int mid=(l+r)/2;
build(ro*2,l,mid);
build(ro*2+1,mid+1,r);
f[ro]=up(f[ro*2],f[ro*2+1]);
}
void update(int ro,int l,int r,int p,int va)
{
if(l==r)
{
for(int i=0;i<=9;i++)
if(va&(1<<i))
f[ro].s[i]=f[ro].t[i]=1;
else
f[ro].s[i]=f[ro].t[i]=0;
return;
}
int mid=(l+r)/2;
if(p<=mid)
update(ro*2,l,mid,p,va);
else
update(ro*2+1,mid+1,r,p,va);
f[ro]=up(f[ro*2],f[ro*2+1]);
}
yy query(int ro,int l,int r,int zuo,int you)
{
if(l>=zuo&&r<=you)
return f[ro];
yy hy=tu;
int mid=(l+r)/2;
if(zuo<=mid)
hy=query(ro*2,l,mid,zuo,you);
if(you>mid)
hy=up(hy,query(ro*2+1,mid+1,r,zuo,you));
return hy;
}
int main()
{
cin>>n>>q;
for(int i=1;i<n;i++)
{
int u,v,va;
read(u);
read(v);
read(va);
add(u,v,va);
add(v,u,va);
}
dfs(1);
dfs2(1,1);
build(1,1,n);
while(q--)
{
int u,v,va,ops;
read(ops);
read(u);
read(v);
if(ops==2)
{
read(va);
if(dep[u]<dep[v])
swap(u,v);
update(1,1,n,dfn[u],va);
}
else
{
yy L=tu,R=tu;
LL ans=0;
while(top[u]!=top[v])
{
if(dep[top[u]]>dep[top[v]])
{
L=up(L,rev(query(1,1,n,dfn[top[u]],dfn[u])));
u=fa[top[u]];
}
else
{
R=up(query(1,1,n,dfn[top[v]],dfn[v]),R);
v=fa[top[v]];
}
}
if(dep[u]>dep[v])
L=up(L,rev(query(1,1,n,dfn[v]+1,dfn[u])));
else
R=up(query(1,1,n,dfn[u]+1,dfn[v]),R);
L=up(L,R);
for(int i=0;i<=9;i++)
ans+=(1ll<<i)*(LL)L.s[i]*(L.len+1-L.s[i]);
printf("%lld\n",ans);
}
}
return 0;
}