洛谷 P4211 [LNOI2014]LCA 解題報告
阿新 • • 發佈:2019-02-01
node include 有一個 std pre truct 合並 oid strong
[LNOI2014]LCA
題意
給一個\(n(\le 50000)\)節點的有根樹,詢問\(l,r,z\),求\(\sum_{l\le i\le r}dep[lca(i,z)]\)
一直想啟發式合並...
關於LCA的深度,有一個轉換。
比如詢問\((x,y)\)的\(lca\)深度,可以把\(x\)到跟每個點染色+1,然後查詢\(y\)到根的權值。
這個題離線進行差分,每次加一個點染色求前綴詢問即可。
Code:
#include <cstdio> #include <cctype> #include <vector> const int N=5e5+10; const int mod=201314; int read() { int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } int n,q,ans[N]; int head[N],to[N],Next[N],cnt; void add(int u,int v) { to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt; } int dfn[N],top[N],f[N],siz[N],ws[N],dfsclock; void dfs1(int now) { siz[now]=1; for(int v,i=head[now];i;i=Next[i]) { f[v=to[i]]=now; dfs1(v); siz[now]+=siz[v]; if(siz[ws[now]]<siz[v]) ws[now]=v; } } void dfs2(int now,int anc) { top[now]=anc; dfn[now]=++dfsclock; if(ws[now]) dfs2(ws[now],anc); for(int v,i=head[now];i;i=Next[i]) if(!dfn[v=to[i]]) dfs2(v,v); } int sum[N<<2],tag[N<<2]; #define ls id<<1 #define rs id<<1|1 void pushdown(int id,int L,int R) { if(tag[id]) { int Mid=L+R>>1; (sum[ls]+=1ll*tag[id]*(Mid+1-L))%=mod; (sum[rs]+=1ll*tag[id]*(R-Mid))%=mod; tag[ls]+=tag[id],tag[rs]+=tag[id]; tag[id]=0; } } void change(int id,int L,int R,int l,int r) { if(l==L&&r==R) { (sum[id]+=R+1-L)%=mod; ++tag[id]; return; } pushdown(id,L,R); int Mid=L+R>>1; if(r<=Mid) change(ls,L,Mid,l,r); else if(l>Mid) change(rs,Mid+1,R,l,r); else change(ls,L,Mid,l,Mid),change(rs,Mid+1,R,Mid+1,r); sum[id]=sum[ls]+sum[rs]; } int query(int id,int L,int R,int l,int r) { if(l==L&&r==R) return sum[id]; pushdown(id,L,R); int Mid=L+R>>1; if(r<=Mid) return query(ls,L,Mid,l,r); else if(l>Mid) return query(rs,Mid+1,R,l,r); else return (query(ls,L,Mid,l,Mid)+query(rs,Mid+1,R,Mid+1,r))%mod; } void modify(int now) { while(top[now]!=top[1]) { change(1,1,n,dfn[top[now]],dfn[now]); now=f[top[now]]; } change(1,1,n,1,dfn[now]); } int ask(int now) { int ret=0; while(top[now]!=top[1]) { (ret+=query(1,1,n,dfn[top[now]],dfn[now]))%=mod; now=f[top[now]]; } (ret+=query(1,1,n,1,dfn[now]))%=mod; return ret; } struct node{int id,z;}bee; std::vector<node> qry[N]; int main() { n=read(),q=read(); for(int i=2;i<=n;i++) add(read()+1,i); dfs1(1),dfs2(1,1); for(int l,r,i=1;i<=q;i++) { l=read()+1,r=read()+1,bee.z=read()+1,bee.id=-i; qry[l-1].push_back(bee); bee.id=i; qry[r].push_back(bee); } for(int i=1;i<=n;i++) { modify(i); for(int j=0;j<qry[i].size();j++) { int id=qry[i][j].id,z=qry[i][j].z; if(id>0) ans[id]+=ask(z); else ans[-id]-=ask(z); } } for(int i=1;i<=q;i++) printf("%d\n",(ans[i]+mod)%mod); return 0; }
2019.2.1
洛谷 P4211 [LNOI2014]LCA 解題報告