Luogu P4211 [LNOI2014]LCA

Luogu P4211 [LNOI2014]LCA

我怀疑我是个脑残+手残

自信点,把怀疑去掉

\(fa[i,d]\)表示\(i\)的一个高度为\(d\)的父亲

\[Dep[lca[i,j]]=\sum [fa[i,d_1]==fa[j,d_2]] \]

所以相当于将在\([l,r]\)到根的链上加1,查询一条到根的链上的值

莽夫可以用可持久化线段树(算算明显爆空间),我一开始想的也是

怂逼可以离散化,将询问拆成\([1,r]-[1,l-1]\),然后求解

又是经典地中途反悔,忘改前面,沃日

#include<bits/stdc++.h>
#define ll long long
const int P=201314;
using namespace std;

const int N=5e4+5,M=1e6+5;
int n,sgn,sz[N],dep[N],dad[N],son[N],top[N],dfn[N],ans[N];
int c[M],t[M];
vector<int>V[N];

struct A{int fh,z,id; };
vector<A>Q[N];
inline int mo(int x) {
	return x>=P?x-P:x;
}
void dfs(int fa,int u) {
	sz[u]=1,dep[u]=dep[fa]+1;
	dad[u]=fa;
	for(auto v:V[u]) {
		if(v!=fa) {
			dfs(u,v);
			sz[u]+=sz[v];
			if(sz[son[u]]<sz[v]) son[u]=v;
		}
	}
}
inline void up(int p) {
	c[p]=mo(c[p<<1]+c[p<<1|1]);
}
inline void down(int p,int l,int r,int mid) {
	if(t[p]) {
		t[p<<1]+=t[p]; c[p<<1]=((ll)t[p]*(mid-l+1)+c[p<<1])%P;
		t[p<<1|1]+=t[p],c[p<<1|1]=((ll)t[p]*(r-mid)+c[p<<1|1])%P; 
		t[p]=0;
	}
}
void add(int p,int l,int r,int x,int y){
	if(l==x&&r==y) {
		c[p]=(c[p]+r-l+1)%P,t[p]++; 
		return;
	}
	int mid=l+r>>1;
	down(p,l,r,mid);
	if(y<=mid) add(p<<1,l,mid,x,y);
		else if(x>mid) add(p<<1|1,mid+1,r,x,y);
			else {
				add(p<<1,l,mid,x,mid);
				add(p<<1|1,mid+1,r,mid+1,y);
			}
	up(p);
}
void dgs(int fa,int u,int t) {
	top[u]=t,dfn[u]=++sgn;
	if(son[u]) dgs(u,son[u],t);
	for(auto v:V[u]) {
		if(v!=fa&&v!=son[u]) {
			dgs(u,v,v);
		}
	}
}
int get(int p,int l,int r,int x,int y) {
	if(l==x&&r==y) return c[p];
	int mid=l+r>>1;
	down(p,l,r,mid);
	if(y<=mid) return get(p<<1,l,mid,x,y);
	if(x>mid) return get(p<<1|1,mid+1,r,x,y);
	return mo(get(p<<1,l,mid,x,mid)+get(p<<1|1,mid+1,r,mid+1,y));
}
int ask(int x) {
	int ret=0;
	while(x) {
		ret=mo(ret+get(1,1,n,dfn[top[x]],dfn[x]));
		x=dad[top[x]];
	}
	return ret; 
}
void addl(int x) {
	while(x) {
		add(1,1,n,dfn[top[x]],dfn[x]);
		x=dad[top[x]];
	}
}
int main(){
	int T; scanf("%d%d",&n,&T);
	for(int i=2;i<=n;i++) {
		int u; scanf("%d",&u); u++;
		V[u].push_back(i),V[i].push_back(u); 
	}
	dfs(0,1),dgs(0,1,1);
	for(int i=1;i<=T;i++) {
		int l,r,z; scanf("%d%d%d",&l,&r,&z),l++,r++,z++;
		Q[l-1].push_back((A){-1,z,i});
		Q[r].push_back((A){1,z,i});
	}
	for(int i=1;i<=n;i++) {
		addl(i);
		for(A v:Q[i]){
			ans[v.id]=v.fh>0?mo(ans[v.id]+ask(v.z)):mo(ans[v.id]-ask(v.z)+P); 
		}
	}
	for(int i=1;i<=T;i++) {
		printf("%d\n",ans[i]);
	}
	return 0;
}
posted @ 2021-03-22 15:17  wwwsfff  阅读(27)  评论(0)    收藏  举报