其他分享
首页 > 其他分享> > [TJOI2018]异或

[TJOI2018]异或

作者:互联网

link

可持久化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