[TJOI2018]异或
作者:互联网
可持久化Trie初学笔记。今天写可持久化数据结构都写烦了。
可持久化Trie长得和主席树颇有几分神似,都是一排根节点然后下面一堆纵横交错的边相互连接(也是,可持久化数据结构的功能注定了它们只能长成这幅模样)。
说回本题。为了实现可持久化,考虑加入一个字符串可能会对Trie造成什么影响。可以想到对于根节点来说,应该会有一条边连向该字符串的对应字符,而除了这条边以外的所有连边信息都应该从上一个状态(其实任意合法状态都可以)继承下来,为的是不丢失信息(也就是你从这个节点出去仍然能访问到之前的节点)。然后往下跳的同时前面的节点也往下跳,以维护合法性。
题目嘛就是一个模板,树上问题转序列,基本操作。其它便没有什么了。
#include<cstdio>
//#define zczc
const int N=100010;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
inline void swap(int &s1,int &s2){
int s3=s1;s1=s2;s2=s3;return;
}
inline int max(int s1,int s2){
return s1<s2?s2:s1;
}
int m,n,a[N];
struct tree{
struct node{
int ch[2],data;
}t[N<<5];
int cnt,root[N];
inline void insert(int x,int ti,int val){
int y=root[ti]=++cnt;
for(int i=30;i>=0;i--){
int now=((val>>i)&1);
t[y].ch[!now]=t[x].ch[!now];
t[y].ch[now]=++cnt;
y=t[y].ch[now],x=t[x].ch[now];
t[y].data=ti;
}
}
inline int work(int l,int r,int val){
int x=root[r],an=0;
for(int i=30;i>=0;i--){
an<<=1;
int now=((val>>i)&1);
if(t[t[x].ch[!now]].data>=l)an+=1,x=t[x].ch[!now];
else x=t[x].ch[now];
}
return an;
}
inline void print(int x,int val){
if(!x)return;
if(t[x].ch[0]==0&&t[x].ch[1]==0){
printf("%d ",val);return;
}
print(t[x].ch[0],val<<1);
print(t[x].ch[1],val<<1|1);
}
}t1,t2;
struct edge{
int t,next;
}e[N<<1];
int head[N],esum;
inline void add(int fr,int to){
e[++esum]=(edge){to,head[fr]};head[fr]=esum;
}
int dfn,vv[N],id[N],size[N],nxt[N][20],d[N];
void dfs(int wh,int fa){
vv[++dfn]=a[wh];id[wh]=dfn;size[wh]=1;
nxt[wh][0]=fa;d[wh]=d[fa]+1;
for(int i=1;i<20;i++)nxt[wh][i]=nxt[nxt[wh][i-1]][i-1];
t1.insert(t1.root[fa],wh,a[wh]);
for(int i=head[wh],th;i;i=e[i].next){
if((th=e[i].t)==fa)continue;
dfs(th,wh);
size[wh]+=size[th];
}
}
int lca(int s1,int s2){
if(d[s1]<d[s2])swap(s1,s2);
for(int i=19;i>=0;i--){
if(d[nxt[s1][i]]>=d[s2])s1=nxt[s1][i];
}
if(s1==s2)return s1;
for(int i=19;i>=0;i--){
if(nxt[s1][i]^nxt[s2][i]){
s1=nxt[s1][i];
s2=nxt[s2][i];
}
}
return nxt[s1][0];
}
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
int s1,s2,s3,op;
read(m);read(n);
for(int i=1;i<=m;i++)read(a[i]);
for(int i=1;i<m;i++){
read(s1);read(s2);
add(s1,s2);add(s2,s1);
}
dfs(1,0);
for(int i=1;i<=m;i++)t2.insert(t2.root[i-1],i,vv[i]);
while(n--){
read(op);read(s1);read(s2);
if(op==1)printf("%d\n",t2.work(id[s1],id[s1]+size[s1]-1,s2));
else{
read(s3);
int ll=lca(s1,s2);
printf("%d\n",max(t1.work(ll,s1,s3),t1.work(ll,s2,s3)));
}
}
return 0;
}
标签:nxt,now,int,s2,s1,异或,ch,TJOI2018 来源: https://www.cnblogs.com/dai-se-can-tian/p/16122017.html