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