求助
查看原帖
求助
1007817
hutao_sdog楼主2024/5/21 15:36

蒟蒻第一次写树分块,成功趋势。最后三个点TLE了,有没有大佬帮忙看一下。

#include<bits/stdc++.h>
using namespace std;
const int N=4e4+10;
int n,m,a[N],ans=0;
int b[N];
int block=0;
int f[N][30],deep[N],Size[N],maxdeep[N];//maxdeep[i]记录i属于的深度为deep[x]~deep[x]+block的块中的最大深度 
int id[N],tot=0;//id标记关键点 
int s[N],ff[N],top=0;//s[i]一条到根的路径上的关键点,ff[i]表示这一条路径上离关键点i最近的祖先关键点 
bitset<N> bt[50][50],record;//维护颜色的出现种类 
int head[N*2],cnt=0;
struct node{
	int v,nex;
}e[N*2];
void add(int u,int v){
	e[++cnt].v=v;
	e[cnt].nex=head[u];
	head[u]=cnt;
}
void dfs1(int u,int fa){
	f[u][0]=fa;
	deep[u]=deep[fa]+1;
	maxdeep[u]=deep[u];
	Size[u]=1;
	for(int i=head[u];i;i=e[i].nex){
		int v=e[i].v;
		if(v==fa) continue;
		dfs1(v,u);
		Size[u]+=Size[v];
		maxdeep[u]=max(maxdeep[u],maxdeep[v]);
	}
	//每次选择一个深度最大的非关键点,若它的1~block级祖先都不是关键点,则我们把它的block级祖先标记为关键点 
	if(maxdeep[u]-deep[u]>=block){
		id[u]=++tot;
		maxdeep[u]=deep[u];//注意改变当前的maxdeep 
	}
}
void dfs2(int u,int fa){
	//考虑一条到根的路径上的所有关键点,用bitset维护它们两两间出现的颜色 
	for(int i=head[u];i;i=e[i].nex){
		int v=e[i].v;
		if(v==fa) continue;
		if(id[v]){
			int last=id[s[top]],now=id[v];
			for(int x=v;x!=s[top];x=f[x][0]){
				bt[last][now].set(a[x]);//将bitset中第a[x]位变成1 
			}
			for(int j=1;j<top;j++){
				bt[id[s[j]]][now]=bt[id[s[j]]][last]|bt[last][now];
			}
			ff[v]=s[top];
			s[++top]=v;
		}
		dfs2(v,u);
		if(id[v]) top--;//注意是一条到根的路径,需要清除 
	}
}
int lca(int x,int y){
	if(deep[x]<deep[y]) swap(x,y);
	for(int i=25;i>=0;i--){
		if(deep[f[x][i]]>=deep[y]){
			x=f[x][i];
		}
	}
	if(x==y) return x;
	for(int i=25;i>=0;i--){
		if(f[x][i]!=f[y][i]){
			x=f[x][i];
			y=f[y][i];
		}
	}
	return f[x][0];
}
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	block=1000;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[i]=a[i];
	}
	sort(b+1,b+n+1);
	int p=unique(b+1,b+n+1)-b-1;
	for(int i=1;i<=n;i++){
		a[i]=lower_bound(b+1,b+p+1,a[i])-b;
	}
	for(int i=1;i<=n-1;i++){
		int u,v;
		cin>>u>>v;
		add(u,v);
		add(v,u);
	}
	dfs1(1,0);
	for(int j=1;j<=25;j++){
		for(int i=1;i<=n;i++){
			f[i][j]=f[f[i][j-1]][j-1];
		}
	}
	if(!id[1]) id[1]=++tot;
	s[++top]=1;
	dfs2(1,0);
	while(m--){
		int u,v;
		cin>>u>>v;
		u^=ans;
		record.reset();//清空record 
		int k=lca(u,v);
		while(u!=k&&!id[u]){
			record.set(a[u]);
			u=f[u][0];
		}
		while(v!=k&&!id[v]){
			record.set(a[v]);
			v=f[v][0];
		}
		if(u!=k){
			int uu=u;
			while(deep[ff[u]]>=deep[k]) uu=ff[uu];
			if(uu!=u) record|=bt[id[uu]][id[u]];
			while(uu!=k){
				record.set(a[uu]);
				uu=f[uu][0];
			}
		}
		if(v!=k){
			int vv=v;
			while(deep[ff[v]]>=deep[k]) vv=ff[vv];
			if(vv!=v) record|=bt[id[vv]][id[v]];
			while(vv!=k){
				record.set(a[vv]);
				vv=f[vv][0];
			}
		}
		record.set(a[k]);
		ans=record.count();
		cout<<ans<<endl;
	}
	return 0;
}
2024/5/21 15:36
加载中...