EOJ Monthly 2020.9 F. 动态树(线段树套字典树)
题目链接
https://acm.ecnu.edu.cn/contest/317/problem/F/
题意
你需要维护一棵动态树,初始状态下仅有一个节点,编号为\(1\),并支持以下操作:
\(Add x y\):插入一个节点,其编号为当前存在的节点数量(包括当前新加入的节点),指定其父节点为\(x\),并添加一条无向边连接新节点和它的父节点,边权为\(y\)。
\(Query x y\):查询起点为\(x\)号节点,终点在\(y\)的子树中(包括\(y\)号节点)的最大简单路径异或和(要求路径不经过重复的节点,且起点与终点不同)。
思路
注意\(1\)号节点的字典树需要插入\(0\)值
#include<bits/stdc++.h>
using namespace std;
const int maxx = 2e5+10;
struct Trie
{
int trie[32*20*maxx][2],tot;
int sum[32*20*maxx];
void init()
{
tot=0;
trie[0][0]=trie[0][1]=sum[0]=0;
}
void update(int rt,int x,int c)
{
for(int i=31;i>=0;i--)
{
int id=(x>>i)&1;
if(!trie[rt][id])
{
trie[rt][id]=++tot;
trie[tot][0]=trie[tot][1]=sum[tot]=0;
}
rt=trie[rt][id];
sum[rt]+=c;
}
}
int query(int rt,int x)
{
int res=0;
for(int i=31;i>=0;i--)
{
int id=(x>>i)&1;
if(trie[rt][id^1]&&sum[trie[rt][id^1]])
rt=trie[rt][id^1],res+=(1<<i);
else rt=trie[rt][id];
}
return res;
}
}trie;
struct Tree
{
int t[maxx<<2];
void build(int l,int r,int rt)
{
t[rt]=++trie.tot;
if(l==r)return;
int mid=(l+r)/2;
build(l,mid,rt*2);
build(mid+1,r,rt*2+1);
}
void update(int l,int r,int k,int x,int c,int rt)
{
trie.update(t[rt],x,c);
if(l==r)return;
int mid=(l+r)/2;
if(k<=mid)update(l,mid,k,x,c,rt*2);
else update(mid+1,r,k,x,c,rt*2+1);
}
int query(int l,int r,int p,int q,int x,int rt)
{
if(p<=l&&r<=q)return trie.query(t[rt],x);
int mid=(l+r)/2;
int res=0;
if(p<=mid)res=max(res,query(l,mid,p,q,x,rt*2));
if(q>mid)res=max(res,query(mid+1,r,p,q,x,rt*2+1));
return res;
}
}tree;
struct edge
{
int to,val,next;
}e[maxx*2];
int head[maxx],tot;
void add(int u,int v,int w)
{
e[++tot].to=v,e[tot].val=w;
e[tot].next=head[u],head[u]=tot;
}
int in[maxx],out[maxx],a[maxx],cnt;
void dfs(int u,int fa)
{
in[u]=++cnt;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa)continue;
a[v]=a[u]^e[i].val;
dfs(v,u);
}
out[u]=cnt;
}
struct node
{
int op,x,y;
}q[maxx];
int main()
{
int Q;
scanf("%d",&Q);
char op[2];
int x,y,tmp;
int n=1;
for(int i=1;i<=Q;i++)
{
scanf("%s%d%d",op,&x,&y);
tmp=(op[0]=='A'?0:1);
if(tmp==0)
{
++n;
add(x,n,y);add(n,x,y);
q[i]=node{tmp,x,n};
}
else q[i]=node{tmp,x,y};
}
dfs(1,0);
trie.init();
tree.build(1,n,1);
tree.update(1,n,1,0,1,1);
for(int i=1;i<=Q;i++)
{
if(q[i].op==0)
{
tree.update(1,n,in[q[i].y],a[q[i].y],1,1);
}
else
{
int ans=tree.query(1,n,in[q[i].y],out[q[i].y],a[q[i].x],1);
printf("%d\n",ans);
}
}
return 0;
}