[LNOI2014]LCA(树链剖分+线段树)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3626
题解:看到LCA,我们可以直接想到这题的正解不是LCA!(LCA只能得20分,还要卡常)
于是我们怎么做呢?
考虑如何求Σdep[lca(i,z)](i∈[l,r]),由于不强制在线,我们不妨考虑离线……考虑每个lca贡献的答案。很显然z的lca在路径[1,z]上,所以我们可以把每一个lca到根的路径中所有点权值都加1,再从z跑一遍加上路径上的点的贡献即可。对于[l,r],可以枚举i,然后i~根路径+1,跑一遍就行了,但这样会TLE,怎么办?很显然就是把[l,r]视为[1,l-1]和[1,r]两部分,答案就是第二部分减去第一部分的值,然后只要开一个vector。从1~n扫一遍然后覆盖,对当前节点vector内的询问做一下query就行了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define lson l,mid,rt*2 #define rson mid+1,r,rt*2+1 using namespace std; const int N=5e4+77,mod=201314; struct node{int id,v,z;}; vector<node>S[N]; vector<int>G[N]; int n,q,cnt,fa[N],sz[N],dep[N],son[N],id[N],top[N],ans[N],sum[N*4],lazy[N*4]; void dfs(int u) { sz[u]=1; for(int i=0;i<G[u].size();i++) { fa[G[u][i]]=u,dep[G[u][i]]=dep[u]+1; dfs(G[u][i]); sz[u]+=sz[G[u][i]]; if(sz[son[u]]<sz[G[u][i]])son[u]=G[u][i]; } } void dfs2(int u,int tp) { id[u]=++cnt,top[u]=tp; if(son[u])dfs2(son[u],tp); for(int i=0;i<G[u].size();i++) if(G[u][i]!=son[u])dfs2(G[u][i],G[u][i]); } void pushdown(int rt,int d) { if(lazy[rt]) { sum[rt*2]=(sum[rt*2]+1ll*lazy[rt]*(d-d/2))%mod; sum[rt*2+1]=(sum[rt*2+1]+1ll*lazy[rt]*(d/2))%mod; lazy[rt*2]=(lazy[rt*2]+lazy[rt])%mod; lazy[rt*2+1]=(lazy[rt*2+1]+lazy[rt])%mod; lazy[rt]=0; } } void update(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R){sum[rt]=(sum[rt]+r-l+1)%mod,lazy[rt]=(lazy[rt]+1)%mod;return;} pushdown(rt,r-l+1); int mid=(l+r)/2; if(L<=mid)update(L,R,lson); if(R>mid)update(L,R,rson); sum[rt]=(sum[rt*2]+sum[rt*2+1])%mod; } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R)return sum[rt]; pushdown(rt,r-l+1); int mid=(l+r)/2,ret=0; if(L<=mid)ret+=query(L,R,lson); if(R>mid)ret+=query(L,R,rson); return ret%mod; } void Update(int x) { while(top[x]!=1)update(id[top[x]],id[x],1,n,1),x=fa[top[x]]; update(id[1],id[x],1,n,1); } int Query(int x) { int ret=0; while(top[x]!=1)ret=(ret+query(id[top[x]],id[x],1,n,1))%mod,x=fa[top[x]]; ret+=query(id[1],id[x],1,n,1); return ret%mod; } int main() { scanf("%d%d",&n,&q); for(int i=2,x;i<=n;i++)scanf("%d",&x),G[x+1].push_back(i); dfs(1),dfs2(1,1); for(int i=1,l,r,z;i<=q;i++) scanf("%d%d%d",&l,&r,&z),S[l].push_back((node){i,-1,z+1}),S[r+1].push_back((node){i,1,z+1}); for(int i=1;i<=n;i++) { Update(i); node x; for(int j=0;j<S[i].size();j++)x=S[i][j],ans[x.id]=(ans[x.id]+x.v*Query(x.z)+mod)%mod; } for(int i=1;i<=q;i++)printf("%d\n",ans[i]); }