西瓜树
题面
给定一棵
对每个点
求每个点的答案。
解法
一道01tire好题(写起来其实也不难)。
首先会发现样例输出里有许多一样的答案,原因是假如树中最大的异或值由x和y贡献,那么凡是子树内不包含x且不包含y的节点的答案都会是这个最大值。
这个最大值可以
这个部分也是
#include<cstdio>
#include<vector>
#include<cstring>
#define zczc
#define ll long long
using namespace std;
const int N=500010;
inline ll read(){
ll wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar(); }
wh*=f;return wh;
}
int m,f[N];
vector<int>son[N];
ll a[N],ans[N];
namespace trie{
struct node{
int next[2];
}newone;
vector<node>ve;
ll nans;
void clear(){
nans=0;
ve.clear();
ve.push_back(newone);
return;
}
void push(ll wh){
bool c[61];
for(int i=0;i<=60;i++)c[i]=(wh&(1ll<<(60-i)))>0;
int now=0;
for(int i=0;i<=60;i++){
if(ve[now].next[c[i]]==0)ve[now].next[c[i]]=ve.size(),ve.push_back(newone);
now=ve[now].next[c[i]];
}
ll an=0;now=0;
for(int i=0;i<=60;i++){
an<<=1;
if(ve[now].next[1-c[i]]){an+=1-c[i];now=ve[now].next[1-c[i]];}
else{an+=c[i];now=ve[now].next[c[i]];}
}
if((wh^an)>nans)nans=(wh^an);
return;
}
ll ask(ll wh){
bool c[61];
for(int i=0;i<=60;i++)c[i]=(wh&(1ll<<(60-i)))>0;
int now=0;ll an=0;
for(int i=0;i<=60;i++){
an<<=1;
if(ve[now].next[1-c[i]]){
an+=1-c[i];
now=ve[now].next[1-c[i]];
}
else{
an+=c[i];
now=ve[now].next[c[i]];
}
}
return an;
}
}
void npush(int wh){
trie::push(a[wh]);
//for(int data:son[wh]){
//npush(data);
//}
for(vector<int>::iterator it=son[wh].begin();it!=son[wh].end();it++){
npush(*it);
}
return;
}
void dfs(int wh,int th){
if(wh==0)return;
dfs(f[wh],wh);
ans[wh]=trie::nans;
trie::push(a[wh]);
//for(int data:son[wh]){
//if(data^th)npush(data);
//}
for(vector<int>::iterator it=son[wh].begin();it!=son[wh].end();it++){
if((*it)^th)npush(*it);
}
return;
}
void solve(int wh){
trie::clear();
dfs(wh,0);
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
memset(ans,-1,sizeof(ans));
m=read();
for(int i=2;i<=m;i++){
f[i]=read();
son[f[i]].push_back(i);
}
for(int i=1;i<=m;i++)a[i]=read();
ll x,y,an=0;int px,py;
trie::clear();
for(int i=1;i<=m;i++){
trie::push(a[i]);
ll nan=trie::ask(a[i]);
if((nan^a[i])>an){
an=nan^a[i];
y=a[i],x=nan;
}
}
for(int i=1;i<=m;i++){
if(a[i]==x)px=i;
else if(a[i]==y)py=i;
}
solve(px);
solve(py);
for(int i=1;i<=m;i++)printf("%lld\n",ans[i]>=0?ans[i]:an);
return 0;
}
update 艹机房不支持C++11,用不了for(data:vector)
的写法。
一如既往,万事胜意
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析