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;
}