TJOI2018 异或
题目链接:戳我
可持久化01trie+树链剖分
其实序列上的大家应该都会做,这个题还不过是把序列上的放到了树上而已。多来一个树剖就可以解决。
dummyummy说可以不用树剖写。。可是我还是不怎么会。。。等他写完了我再放那种解法的吧。。。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 200010
using namespace std;
int n,m,t,dfn,tot;
int head[MAXN<<1],wt[MAXN],rt[MAXN],ch[MAXN*32][2],cnt[MAXN*32];
int siz[MAXN],id[MAXN],w[MAXN],fa[MAXN],son[MAXN],top[MAXN],dep[MAXN];
struct Edge{int nxt,to;}edge[MAXN<<1];
inline void add(int from,int to)
{
edge[++t].nxt=head[from],edge[t].to=to,head[from]=t;
edge[++t].nxt=head[to],edge[t].to=from,head[to]=t;
}
inline void dfs1(int x,int pre)
{
siz[x]=1;
fa[x]=pre;
dep[x]=dep[pre]+1;
int maxx=-1;
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==pre) continue;
dfs1(v,x);
siz[x]+=siz[v];
if(siz[v]>maxx) maxx=siz[v],son[x]=v;
}
}
inline void dfs2(int x,int topf)
{
top[x]=topf;
id[x]=++dfn;
w[dfn]=wt[x];
if(son[x]) dfs2(son[x],topf);
for(int i=head[x];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v==fa[x]||v==son[x]) continue;
dfs2(v,v);
}
}
inline void insert(int x,int f,int sum)
{
for(int i=31;i>=0;i--)
{
int v=((sum>>i)&1);
ch[x][!v]=ch[f][!v];
ch[x][v]=++tot;
cnt[ch[x][v]]=cnt[ch[f][v]]+1;
x=ch[x][v],f=ch[f][v];
}
}
inline int query(int f,int x,int sum)
{
int cur_ans=0;
for(int i=31;i>=0;i--)
{
int v=((sum>>i)&1);
if(cnt[ch[x][!v]]>cnt[ch[f][!v]])
{
cur_ans+=(1<<i);
x=ch[x][!v],f=ch[f][!v];
}
else x=ch[x][v],f=ch[f][v];
}
return cur_ans;
}
inline int solve(int x,int y,int z)
{
int cur_ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
cur_ans=max(cur_ans,query(rt[id[top[x]]-1],rt[id[x]],z));
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
cur_ans=max(cur_ans,query(rt[id[x]-1],rt[id[y]],z));
return cur_ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&wt[i]);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
dfs1(1,0);
dfs2(1,1);
rt[0]=++tot;
insert(rt[0],0,0);
//for(int i=1;i<=n;i++) printf("i=%d fa=%d w=%d\n",i,fa[i],w[i]);
//for(int i=1;i<=n;i++) printf("i=%d id=%d siz=%d\n",i,id[i],siz[i]);
for(int i=1;i<=n;i++) rt[i]=++tot,insert(rt[i],rt[i-1],w[i]);
//for(int i=1;i<=n;i++) printf("rt[%d]=%d\n",i,rt[i]);
for(int i=1;i<=m;i++)
{
int op,x,y,z;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&x,&y);
//printf("op=%d x=%d y=%d\n",op,x,y);
printf("%d\n",query(rt[id[x]-1],rt[id[x]+siz[x]-1],y));
}
else
{
scanf("%d%d%d",&x,&y,&z);
//printf("op=%d x=%d y=%d z=%d\n",op,x,y,z);
printf("%d\n",solve(x,y,z));
}
}
return 0;
}