题解:CF1980G Yasya and the Mysterious Tree
题意
一棵有边权的树,存在两种操作:
^ x:所有边权异或x。? v x:新建一条一端为v边权为x的边,你可以选择不为v的任意点u作为边的另一端 ,最大化在环上的边的边权异或和。
操作
Sol
疑惑题!
先不管修改操作。
把一个环分成三部分,
为了方便表示,记
如果多组询问每次给定
所以维护每个点到根节点路径上边权异或和即可求解。
现在
具体来说,把所有
现在考虑带修改如何做,如果只修改一条边的话会变得很复杂(也许是我太菜了),但是题目要的是全局异或,这就很容易了,可以类似懒标记给全局打 tag 并且标记永久化,设异或值为
我们只关心一个点到根节点的异或和,设根节点深度为
由于深度为奇数的点不需要异或,而偶数的点需要,考虑建两颗 01trie,分别在奇数树和偶数树上以不同的异或值查找。
具体来说,经过修改后当前节点到根节点的路径异或和为
本题充分使用了异或的交换律。
时间复杂度
Code
#include<bits/stdc++.h>
#define ll long long
#define N 200005
#define endl "\n"
#define fi first
#define se second
using namespace std;
const ll mod=1e9+7;
const ll inf=1e18;
const double eps=1e-6;
vector<pair<ll,ll> >v[N];
ll x2[35];
ll n,m;
struct trie{
ll cnt,tr[N*34][2],rt,num[N*34];
void ins(ll &p,ll x,ll d){
if(!p)p=++cnt;
num[p]++;
if(d<0)return ;
if((x>>d)&1)ins(tr[p][1],x,d-1);
else ins(tr[p][0],x,d-1);
}
ll qr(ll p,ll x,ll d){
if(d<0)return 0;
ll t=(x>>d)&1;
if(tr[p][t^1])return x2[d]+qr(tr[p][t^1],x,d-1);
return qr(tr[p][t],x,d-1);
}
void del(ll &p,ll x,ll d){
num[p]--;
if(d<0){
if(num[p]==0)p=0;
return ;
}
if((x>>d)&1)del(tr[p][1],x,d-1);
else del(tr[p][0],x,d-1);
if(num[p]==0)p=tr[p][1]=tr[p][0]=0;
}
}T[2];
ll dep[N],f[N];
void dfs(ll x,ll fa){
dep[x]=dep[fa]+1;
T[dep[x]&1].ins(T[dep[x]&1].rt,f[x],33);
for(auto [y,val]:v[x]){
if(y==fa)continue;
f[y]=f[x]^val;
dfs(y,x);
}
}
void sol(){
cin>>n>>m;
for(int i=1;i<n;i++){
ll x,y,z;
cin>>x>>y>>z;
v[x].push_back({y,z});
v[y].push_back({x,z});
}
dfs(1,0);
ll k=0;
for(int i=1;i<=m;i++){
char c;
ll x,val;
cin>>c;
if(c=='^'){
cin>>val;
k^=val;
}else{
cin>>x>>val;
T[dep[x]&1].del(T[dep[x]&1].rt,f[x],33);
ll w=((dep[x]&1)?f[x]:(f[x]^k));
ll p=max(T[0].qr(T[0].rt,w^val^k,33),T[1].qr(T[1].rt,w^val,33));
cout<<p<<" ";
T[dep[x]&1].ins(T[dep[x]&1].rt,f[x],33);
}
}
for(int i=1;i<=n;i++){
v[i].clear();
T[dep[i]&1].del(T[dep[i]&1].rt,f[i],33);
}
T[1].cnt=T[0].cnt=0;
cout<<endl;
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
x2[0]=1;
for(int i=1;i<=33;i++)x2[i]=x2[i-1]*2;
ll ttt;
cin>>ttt;
while(ttt--)sol();
return 0;
}