ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[TJOI2018]异或

2022-04-09 15:03:27  阅读:156  来源: 互联网

标签:nxt now int s2 s1 异或 ch 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有