题解: 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;
}