#Trie#洛谷 6018 [Ynoi2010] Fusion tree
题目
给定一棵树,树上每个节点都有点权,需要实现三种操作,
第一种是将与 相邻的所有节点点权加一,第二种是单点减小点权,
第三种是查询与 相邻的所有节点点权的异或和
分析
相邻实际上就是父节点和子节点,不妨将其拆开考虑,
需要解决单点查询单点修改的问题,考虑维护 棵 Trie 求子节点异或和
由低位到高位建树,实际上
加一实际上就是进位的问题,那么 结尾的数都会变成零,
实际上就是 和 的交换
然后 为根节点而没有父节点,直接单独维护即可,时间复杂度
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=1234567; struct node{int y,next;}e[N];
int fat[N],as[N],et=1,n,Q,tot,rt[N],a[N],trie[N*20][2],c[N*20],ed[N*20],w[N*20],fa[N*20];
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
void dfs(int x,int fa){
fat[x]=fa;
for (int i=as[x];i;i=e[i].next)
if (e[i].y!=fa) dfs(e[i].y,x);
}
void update(int rt,int x,int i,int opt){
if (opt==-1){
--c[ed[i]];
for (int p=ed[i];fa[p];p=fa[p],--c[p])
w[fa[p]]=(w[trie[fa[p]][0]]^w[trie[fa[p]][1]])<<1|(c[trie[fa[p]][1]]&1);
ed[i]=0;
}else{
for (int j=0;j<20;++j){
int z=x&1; x>>=1;
if (!trie[rt][z]) trie[rt][z]=++tot;
fa[trie[rt][z]]=rt,rt=trie[rt][z];
}
++c[ed[i]=rt];
for (int p=ed[i];fa[p];p=fa[p],++c[p])
w[fa[p]]=(w[trie[fa[p]][0]]^w[trie[fa[p]][1]])<<1|(c[trie[fa[p]][1]]&1);
}
}
void plusone(int rt){
swap(trie[rt][0],trie[rt][1]);
if (trie[rt][0]) plusone(trie[rt][0]);
w[rt]=(w[trie[rt][0]]^w[trie[rt][1]])<<1|(c[trie[rt][1]]&1);
}
int query(int x){
int ans=0;
for (int p=ed[x];fa[p];p=fa[p])
if (trie[fa[p]][1]==p) ans=ans<<1|1;
else ans<<=1;
return ans;
}
int main(){
n=iut(),Q=iut();
for (int i=1;i<n;++i){
int x=iut(),y=iut();
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}
dfs(1,0),tot=n;
for (int i=1;i<=n;++i) rt[i]=i;
for (int i=1;i<=n;++i){
a[i]=iut();
if (fat[i]) update(rt[fat[i]],a[i],i,1);
}
for (int i=1;i<=Q;++i)
switch (iut()){
case 1:{
int x=iut();
if (fat[x]==1) ++a[1];
else if (fat[fat[x]]){
int z=query(fat[x]);
update(rt[fat[fat[x]]],z,fat[x],-1);
update(rt[fat[fat[x]]],z+1,fat[x],1);
}
plusone(rt[x]);
break;
}
case 2:{
int x=iut(),y=iut();
if (x==1) a[x]-=y;
else{
int z=query(x);
update(rt[fat[x]],z,x,-1);
update(rt[fat[x]],z-y,x,1);
}
break;
}
case 3:{
int x=iut(),z=w[rt[x]];
if (fat[fat[x]]) z^=query(fat[x]);
else if (fat[x]==1) z^=a[1];
print(z),putchar(10);
break;
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构