1. 程式人生 > >[LNOI2014]LCA(樹鏈剖分+線段樹)

[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就行了

#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]); }
View Code