【[SCOI2015]情報傳遞】
阿新 • • 發佈:2019-01-02
非常無腦的板子題,就當是練一下板子
我們可以先將所有的操作離線下來,之後那些蒐集過情報的點就有了點權,對於查詢操作,就是查詢一下這條路徑上有幾個點點權滿足\(st<=now-C+1\)
#include<iostream> #include<cstdio> #include<cstring> #define re register #define maxn 200005 int n,cnt,tot,m,num; int l[maxn*29],r[maxn*29],d[maxn*29]; int rt[maxn],a[maxn]; int cur; int X[maxn],Y[maxn],C[maxn],Day[maxn]; int build(int x,int y) { int root=++cnt; if(x==y) return root; int mid=x+y>>1; l[root]=build(x,mid),r[root]=build(mid+1,y); return root; } int change(int pre,int x,int y,int pos) { int root=++cnt; d[root]=d[pre]+1; if(x==y) return root; l[root]=l[pre],r[root]=r[pre]; int mid=x+y>>1; if(pos<=mid) l[root]=change(l[pre],x,mid,pos); else r[root]=change(r[pre],mid+1,y,pos); return root; } struct E { int v,nxt; }e[maxn<<1]; int head[maxn],sum[maxn],son[maxn],top[maxn],fa[maxn],deep[maxn]; inline void add_edge(int x,int y) { e[++num].v=y; e[num].nxt=head[x]; head[x]=num; } void dfs1(int x) { rt[x]=change(rt[fa[x]],1,n+1,a[x]); sum[x]=1; int maxx=-1; for(re int i=head[x];i;i=e[i].nxt) if(!deep[e[i].v]) { deep[e[i].v]=deep[x]+1; fa[e[i].v]=x; dfs1(e[i].v); sum[x]+=sum[e[i].v]; if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v; } } void dfs2(int x,int topf) { top[x]=topf; if(!son[x]) return; dfs2(son[x],topf); for(re int i=head[x];i;i=e[i].nxt) if(deep[e[i].v]>deep[x]&&e[i].v!=son[x]) dfs2(e[i].v,e[i].v); } inline int LCA(int x,int y) { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) std::swap(x,y); x=fa[top[x]]; } if(deep[x]<deep[y]) return x; return y; } inline int read() { char c=getchar(); int x=0; while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); return x; } int query(int p1,int p2,int p3,int p4,int x,int y,int ll,int rr) { if(ll<=x&&rr>=y) return d[p1]+d[p2]-d[p3]-d[p4]; int mid=x+y>>1; if(rr<=mid) return query(l[p1],l[p2],l[p3],l[p4],x,mid,ll,rr); if(ll>mid) return query(r[p1],r[p2],r[p3],r[p4],mid+1,y,ll,rr); return query(l[p1],l[p2],l[p3],l[p4],x,mid,ll,rr)+query(r[p1],r[p2],r[p3],r[p4],mid+1,y,ll,rr); } int main() { n=read(); int RT=0,x; for(re int i=1;i<=n;i++) { x=read(); if(!x) RT=i; else add_edge(x,i); } rt[0]=build(1,n+1); m=read(); int opt; for(re int i=1;i<=m;i++) { opt=read(); if(opt==1) X[++cur]=read(),Y[cur]=read(),C[cur]=read(),Day[cur]=i; else a[read()]=i; } for(re int i=0;i<=n+1;i++) if(!a[i]) a[i]=n+1; rt[0]=change(rt[0],1,n+1,n+1); deep[RT]=1,dfs1(RT),dfs2(RT,RT); for(re int i=1;i<=cur;i++) { int lca=LCA(X[i],Y[i]); printf("%d ",deep[X[i]]+deep[Y[i]]-2*deep[lca]+1); if(Day[i]-C[i]-1<1) puts("0"); else printf("%d\n",query(rt[X[i]],rt[Y[i]],rt[lca],rt[fa[lca]],1,n+1,1,Day[i]-C[i]-1)); } return 0; }