洛谷P4216 [SCOI2015]情报传递(树剖+主席树)

传送门

 

我们可以进行离线处理,把每一个情报员的权值设为它开始收集情报的时间

那么设询问的时间为$t$,就是问路径上有多少个情报员的权值小于等于$t-c-1$

这个只要用主席树上树就可以解决了,顺便用树剖求一下LCA

 1 //minamoto
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 5 char buf[1<<21],*p1=buf,*p2=buf;
 6 inline int read(){
 7     #define num ch-'0'
 8     char ch;bool flag=0;int res;
 9     while(!isdigit(ch=getc()))
10     (ch=='-')&&(flag=true);
11     for(res=num;isdigit(ch=getc());res=res*10+num);
12     (flag)&&(res=-res);
13     #undef num
14     return res;
15 }
16 char sr[1<<21],z[20];int C=-1,Z;
17 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
18 inline void print(int x,char ch){
19     if(C>1<<20)Ot();
20     while(z[++Z]=x%10+48,x/=10);
21     while(sr[++C]=z[Z],--Z);sr[++C]=ch;
22 }
23 const int N=3e5+5,M=N*32;
24 struct node{int u,v,c,id;}q[N];
25 int head[N],Next[N],ver[N],tot;
26 inline void add(int u,int v){
27     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
28 }
29 int L[M],R[M],sum[M],rt[N],cnt;
30 void update(int last,int &now,int l,int r,int x){
31     sum[now=++cnt]=sum[last]+1;
32     if(l==r) return;
33     int mid=(l+r)>>1;
34     if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x);
35     else L[now]=L[last],update(R[last],R[now],mid+1,r,x);
36 }
37 int fa[N],dep[N],top[N],sz[N],son[N],val[N],root,n,m,k;
38 void dfs1(int u){
39     sz[u]=1,dep[u]=dep[fa[u]]+1;
40     update(rt[fa[u]],rt[u],1,m,val[u]);
41     for(int i=head[u];i;i=Next[i]){
42         int v=ver[i];
43         dfs1(v),sz[u]+=sz[v];
44         if(sz[son[u]]<sz[v]) son[u]=v;
45     }
46 }
47 void dfs2(int u,int t){
48     top[u]=t;
49     if(son[u]){
50         dfs2(son[u],t);
51         for(int i=head[u];i;i=Next[i])
52         if(ver[i]!=son[u]) dfs2(ver[i],ver[i]);
53     }
54 }
55 inline int LCA(int u,int v){
56     while(top[u]!=top[v])
57     dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
58     return dep[u]<dep[v]?u:v;
59 }
60 int query(int u,int v,int lca,int lca_fa,int l,int r,int x){
61     if(r<=x) return sum[u]+sum[v]-sum[lca]-sum[lca_fa];
62     if(l>x) return 0;
63     int mid=(l+r)>>1,res=0;
64     if(x>=l) res+=query(L[u],L[v],L[lca],L[lca_fa],l,mid,x);
65     if(x>mid) res+=query(R[u],R[v],R[lca],R[lca_fa],mid+1,r,x);
66     return res;
67 }
68 int main(){
69 //    freopen("testdata.in","r",stdin);
70     n=read();
71     for(int i=1;i<=n;++i){fa[i]=read(),add(fa[i],i);if(fa[i]==0) root=i;}
72     m=read();for(int i=1;i<=n;++i) val[i]=m;
73     for(int i=1;i<=m;++i){
74         int op=read(),p;
75         if(op&1) q[++k].u=read(),q[k].v=read(),q[k].c=read(),q[k].id=i;
76         else val[p=read()]=i;
77     }
78     dfs1(root),dfs2(root,root);
79     for(int i=1;i<=k;++i){
80         int u=q[i].u,v=q[i].v,lca=LCA(u,v),lca_fa=fa[lca];
81         print(dep[u]+dep[v]-2*dep[lca]+1,' ');
82         int t=q[i].id-q[i].c-1;
83         print(t>0?query(rt[u],rt[v],rt[lca],rt[lca_fa],1,m,t):0,'\n');
84     }
85     Ot();
86     return 0;
87 }

 

posted @ 2018-10-16 13:53  bztMinamoto  阅读(216)  评论(0编辑  收藏  举报
Live2D