BZOJ 3626 [LNOI2014]LCA

Posted ws_zzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 3626 [LNOI2014]LCA相关的知识,希望对你有一定的参考价值。

题解: dep[LCA(a,b)]等价于把a到根路径+1,然后询问b到根路径的权值

按左右端点分别排序求出值后作差就可以了

分块TLE了QWQ

 

LCT代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=50009;
const int mm=201314;

int n,T;

int fa[maxn],ch[maxn][2],siz[maxn],tag[maxn],sum[maxn],v[maxn];
inline int son(int x){
	if(ch[fa[x]][1]==x)return 1;
	else return 0;
}
inline bool isroot(int x){
	return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
}
inline void pushup(int x){
	sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+v[x])%mm;
	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
inline void pushdown(int x){
	if(tag[x]){
		if(ch[x][0]){
			tag[ch[x][0]]+=tag[x];
			v[ch[x][0]]+=tag[x];
			sum[ch[x][0]]=(sum[ch[x][0]]+1LL*siz[ch[x][0]]*tag[x])%mm;
		}
		if(ch[x][1]){
			tag[ch[x][1]]+=tag[x];
			v[ch[x][1]]+=tag[x];
			sum[ch[x][1]]=(sum[ch[x][1]]+1LL*siz[ch[x][1]]*tag[x])%mm;
		}
		tag[x]=0;
	}
}
void Downfa(int x){
	if(!isroot(x))Downfa(fa[x]);
	pushdown(x);
}

inline void Rotate(int x){
	int y=fa[x];
	int z=fa[y];
	int b=son(x),c=son(y);
	int a=ch[x][b^1];
	if(!isroot(y))ch[z][c]=x;
	fa[x]=z;
	if(a)fa[a]=y;
	ch[y][b]=a;
	fa[y]=x;ch[x][b^1]=y;
	pushup(y);pushup(x);
}

void Splay(int x){
	Downfa(x);
	while(!isroot(x)){
		int y=fa[x];
		if(isroot(y)){
			Rotate(x);
		}else{
			if(son(x)==son(y)){
				Rotate(y);Rotate(x);
			}else{
				Rotate(x);Rotate(x);
			}
		}
	}
}

void Access(int x){
	for(int t=0;x;t=x,x=fa[x]){
		Splay(x);ch[x][1]=t;pushup(x);
	}
}
int Querysum(int x){
	Access(x);Splay(x);return sum[x];
}
void Addpoint(int x){
	Access(x);Splay(x);
	tag[x]+=1;v[x]+=1;
	sum[x]=(sum[x]+siz[x])%mm;
}

int ql[maxn],qr[maxn],qz[maxn],ans[maxn];
vector<int>G[maxn];
int cnt[maxn];
int main(){
	scanf("%d%d",&n,&T);
	for(int i=2;i<=n;++i){
		int x;
		scanf("%d",&x);
		++x;
		fa[i]=x;
	}
	for(int i=1;i<=T;++i){
		scanf("%d%d%d",&ql[i],&qr[i],&qz[i]);
		++ql[i];++qr[i];++qz[i];
	}
	
	for(int i=1;i<=n;++i)siz[i]=1;
	
	for(int i=1;i<=T;++i){
		G[ql[i]].push_back(i);
	}
	for(int i=1;i<=n;++i){
		for(int j=0;j<G[i].size();++j){
			int t=G[i][j];
			++cnt[t];
			ans[t]=-Querysum(qz[t]);
		}
		Addpoint(i);
	}
	
	memset(tag,0,sizeof(tag));
	memset(sum,0,sizeof(sum));
	memset(v,0,sizeof(v));
	for(int i=1;i<=n;++i)G[i].clear();
	
	for(int i=1;i<=T;++i){	
		G[qr[i]].push_back(i);
	}
	for(int i=1;i<=n;++i){
		Addpoint(i);
		for(int j=0;j<G[i].size();++j){
			int t=G[i][j];
			++cnt[t];
			ans[t]=(Querysum(qz[t])+ans[t]+mm)%mm;
		}
	}
	
	for(int i=1;i<=T;++i)printf("%d\n",ans[i]);
	return 0;
}

  

分块代码

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=50009;
const int B=120;
const int mm=201314;

int n,T;
int cntedge;
int head[maxn];
int to[maxn<<1],nex[maxn<<1];
void Addedge(int x,int y){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	head[x]=cntedge;
}

int dfsclock;
int father[maxn],dep[maxn],idp[maxn],siz[maxn];
void Dfs(int now,int fa){
	father[now]=fa;
	dep[now]=dep[fa]+1;
	idp[now]=++dfsclock;
	siz[now]=1;
	for(int i=head[now];i;i=nex[i]){
		if(to[i]==fa)continue;
		Dfs(to[i],now);
		siz[now]+=siz[to[i]];
	}
}

int f[maxn][maxn/B+1];

int h[maxn];
void Dp0(int x,int fa){
	for(int i=head[x];i;i=nex[i]){
		if(to[i]==fa)continue;
		Dp0(to[i],x);
		h[x]+=h[to[i]];
	}
}
void Dp(int x,int fa,int sum,int nowb){
	f[x][nowb]=sum;
	
	for(int i=head[x];i;i=nex[i]){
		if(to[i]==fa)continue;
		Dp(to[i],x,(sum+h[to[i]])%mm,nowb);
	}
}

int g[maxn][16];
void LCAinit(){
	for(int i=1;i<=n;++i)g[i][0]=father[i];
	for(int j=1;j<=15;++j){
		for(int i=1;i<=n;++i){
			g[i][j]=g[g[i][j-1]][j-1];
		}
	}
}
int Getlca(int u,int v){
	if(dep[u]<dep[v])swap(u,v);
	for(int j=15;j>=0;--j){
		if(dep[g[u][j]]>=dep[v]){
			u=g[u][j];
		}
	}
	if(u==v)return u;
	for(int j=15;j>=0;--j){
		if(g[u][j]!=g[v][j]){
			u=g[u][j];v=g[v][j];
		}
	}
	return g[u][0];
}

int main(){
	scanf("%d%d",&n,&T);
	for(int i=2;i<=n;++i){
		int x;
		scanf("%d",&x);
		++x;
		Addedge(x,i);
	}
	
	Dfs(1,0);
	LCAinit();
	
	for(int i=1;i<=n;++i){
		h[i]=1;
		if(i%B==0){
			Dp0(1,0);
			Dp(1,0,B,i/B);
			memset(h,0,sizeof(h));
		}
	}
	
	while(T--){
		int l,r,x;
		scanf("%d%d%d",&l,&r,&x);
		++l;++r;++x;
		int ans=0;
		int bl=(l-1)/B+1;
		int br=(r-1)/B+1;
		if(bl==br){
			for(int i=l;i<=r;++i){
				ans=(ans+dep[Getlca(i,x)])%mm;
			}
		}else{
			for(int i=bl+1;i<=br-1;++i)ans=(ans+f[x][i])%mm;
			for(int i=l;i<=bl*B;++i)ans=(ans+dep[Getlca(i,x)])%mm;
			for(int i=(br-1)*B+1;i<=r;++i)ans=(ans+dep[Getlca(i,x)])%mm;
		}
		printf("%d\n",ans);
	}
	return 0;
}

  

以上是关于BZOJ 3626 [LNOI2014]LCA的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3626: [LNOI2014]LCA

Bzoj3626 [LNOI2014]LCA

BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

bzoj3626 [LNOI2014]LCA

BZOJ3626[LNOI2014]LCA 离线+树链剖分+线段树

bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)