洛谷 4216 BZOJ 4448 [SCOI2015]情报传递

【题解】

  每个情报员的危险值val[i]应该是一个分段函数,前面一段是平行于x轴的横线,后面一段是一次函数。我们可以用fx(t)=t-b[x]表示这个一次函数。每次询问一条链上fx(t)大于c的点的个数,也就是问有多少个点满足t-b[x]>c,移项得b[x]<t-c,不等式左边只与点有关,可以当做点权,右边只与询问有关。因此我们可以写没有修改的主席树。

  同时这道题也可以离线后用树状数组写。我们维护某个点到根的链上小于等于某个值的数的个数Cnt,这开一个权值树状数组就可以做到。这样每个询问(x,y)的答案就是Cnt[x]+Cnt[y]-Cnt[lca]-Cnt[fa[lca]]. 我们dfs进行维护,进入这个点的时候在树状数组中加入点权,退出这个点的时候删除点权,同时在每个点计算与这个点有关的答案即可。

  

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<queue>
 4 #define N 200010
 5 #define rg register
 6 using namespace std;
 7 int n,m,rt,tot,cnt,ret,last[N],ans[N],ans2[N],fa[N],hvy[N],size[N],top[N],dep[N],t[N],val[N];
 8 vector<int>son[N];
 9 struct rec{
10     int pos,val,type,pre;
11 }data[N<<2];
12 inline int read(){
13     int k=0,f=1; char c=getchar();
14     while(c<'0'||c>'9')c=getchar();
15     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
16     return k*f;
17 }
18 void dfs1(int x){
19     size[x]=1; dep[x]=dep[fa[x]]+1;
20     for(rg int i=0,s;i<son[x].size();i++){
21         dfs1(s=son[x][i]); size[x]+=size[s];
22         if(size[s]>size[hvy[x]]) hvy[x]=s;
23     }
24 }
25 void dfs2(int x,int tp){
26     top[x]=tp;
27     if(hvy[x]) dfs2(hvy[x],tp);
28     for(rg int i=0,s;i<son[x].size();i++)
29         if((s=son[x][i])!=hvy[x]) dfs2(s,s);    
30 }
31 inline int lca(int x,int y){
32     int f1=top[x],f2=top[y];
33     while(f1!=f2){
34         if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
35         x=fa[f1]; f1=top[x];
36     }
37     return dep[x]<dep[y]?x:y;
38 }
39 void dfs(int x){
40     for(rg int i=val[x];i<=m;i+=(i&-i)) t[i]++;
41     for(rg int i=last[x];i;i=data[i].pre){
42         ret=0;
43         for(rg int j=data[i].val-1;j>0;j-=(j&-j)) ret+=t[j];
44         ans[data[i].pos]+=data[i].type*ret;
45     }
46     for(rg int i=0;i<son[x].size();i++) dfs(son[x][i]);
47     for(rg int i=val[x];i<=m;i+=(i&-i)) t[i]--;
48 }
49 int main(){
50     n=read();
51     for(rg int i=1;i<=n;i++){
52         fa[i]=read();
53         if(!fa[i]) rt=i;
54         son[fa[i]].push_back(i);
55     }
56     m=read();
57     for(rg int i=1;i<=n;i++) val[i]=m;
58     dfs1(rt); dfs2(rt,rt);
59     for(rg int t=1;t<=m;t++){
60         int opt=read();
61         if(opt==1){
62             int x=read(),y=read(),c=read(),Lca=lca(x,y);
63             data[++tot]=(rec){++cnt,t-c,1,last[x]}; last[x]=tot;
64             data[++tot]=(rec){cnt,t-c,1,last[y]}; last[y]=tot;
65             data[++tot]=(rec){cnt,t-c,-1,last[Lca]}; last[Lca]=tot;
66             data[++tot]=(rec){cnt,t-c,-1,last[fa[Lca]]}; last[fa[Lca]]=tot; 
67             ans2[cnt]=dep[x]+dep[y]-2*dep[Lca]+1;
68         }
69         else{
70             int x=read(); if(val[x]==m) val[x]=t;
71         }
72     }
73     dfs(rt);
74     for(rg int i=1;i<=cnt;i++) printf("%d %d\n",ans2[i],ans[i]);
75     return 0;
76 }
View Code

 

posted @ 2018-04-02 19:51  Driver_Lao  阅读(238)  评论(0编辑  收藏  举报