BZOJ4448:[SCO2015]情报传递

题目大意:给你一棵树,有两种操作,一个是修改某个点的权值,另一个是询问两点之间的距离以及路径上小于某个值的数的个数。                                         

询问两点之间距离直接lca即可,对于求个数的问题可以用主席树完成。                                                                                                   

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 inline int read(){
  4     int s=0;char ch=getchar();
  5     for(;ch<'0'||ch>'9';ch=getchar());
  6     for(;ch>='0'&&ch<='9';ch=getchar())s=s*10+ch-'0';
  7     return s;
  8 }
  9 int N,Q;
 10 struct node{
 11     int opt,x,y,c,t;
 12 }q[200010];
 13 int to[200010],next[200010],tot,h[200010];
 14 int root[200010],ls[4000010],rs[4000010],size[4000010];
 15 int c[200010],rt,cnt;
 16 int fa[200010][19],dep[200010];
 17 void add(int x,int y){
 18     tot++;to[tot]=y;next[tot]=h[x];h[x]=tot;
 19 }
 20 void insert(int l,int r,int Ort,int Nrt,int x){
 21     if(l==r){size[Nrt]=size[Ort]+1;return;}
 22     int mid=(l+r)>>1;
 23     if(x<=mid){
 24         ls[Nrt]=++cnt;
 25         rs[Nrt]=rs[Ort];
 26         insert(l,mid,ls[Ort],ls[Nrt],x);
 27     }else{
 28         rs[Nrt]=++cnt;
 29         ls[Nrt]=ls[Ort];
 30         insert(mid+1,r,rs[Ort],rs[Nrt],x);
 31     }
 32     size[Nrt]=size[ls[Nrt]]+size[rs[Nrt]];
 33 }
 34 void dfs(int x){
 35     for(int i=1;i<=18;++i)
 36         if(dep[x]<(1<<i))break;
 37         else fa[x][i]=fa[fa[x][i-1]][i-1];
 38     for(int i=h[x];i;i=next[i]){
 39         int v=to[i];
 40         if(dep[v])continue;
 41         dep[v]=dep[x]+1;
 42         fa[v][0]=x;
 43         if(c[v])insert(1,Q,root[x],root[v]=++cnt,c[v]);
 44         else root[v]=root[x];
 45         dfs(v);
 46     }
 47 }
 48 void init(){
 49     N=read();
 50     for(int i=1;i<=N;++i){
 51         int x=read();
 52         if(x==0)rt=i;
 53         else add(x,i);
 54     }
 55     Q=read();
 56     for(int i=1;i<=Q;++i){
 57         q[i].opt=read();
 58         if(q[i].opt==1)q[i].x=read(),q[i].y=read(),q[i].c=read();
 59         else{
 60             q[i].t=read();
 61             if(!c[q[i].t])c[q[i].t]=i;
 62         }
 63     }
 64     dep[rt]=1;
 65     if(c[rt])insert(1,Q,root[0],root[rt]=++cnt,c[rt]);
 66     dfs(rt);
 67 }
 68 int lca(int x,int y){
 69     if(dep[x]<dep[y])swap(x,y);
 70     int d=dep[x]-dep[y];
 71     for(int i=0;i<=18;++i)
 72         if(d&(1<<i))
 73             x=fa[x][i];
 74     if(x==y)return x;
 75     for(int i=18;i>=0;--i)
 76         if(fa[x][i]!=fa[y][i])
 77             x=fa[x][i],y=fa[y][i];
 78     if(x==y)return x;
 79     return fa[x][0];
 80 }
 81 int ask(int l,int r,int rrt,int lrt,int x){
 82     if(x<=0)return 0;
 83     if(l==r)return size[rrt]-size[lrt];
 84     int mid=(l+r)>>1;
 85     if(x<=mid)return ask(l,mid,ls[rrt],ls[lrt],x);
 86     else return size[ls[rrt]]-size[ls[lrt]]+ask(mid+1,r,rs[rrt],rs[lrt],x);
 87 }
 88 void work(){
 89     for(int i=1;i<=Q;++i){
 90         if(q[i].opt==1){
 91             int k=lca(q[i].x,q[i].y);
 92             int k1=dep[q[i].x]+dep[q[i].y]-2*dep[k]+1;
 93             int k2=ask(1,Q,root[q[i].x],root[fa[k][0]],i-q[i].c-1)+ask(1,Q,root[q[i].y],root[k],i-q[i].c-1);
 94             printf("%d %d\n",k1,k2);
 95         }
 96     }
 97 }
 98 int main(){
 99     init();
100     work();
101     return 0;
102 }
View Code

 

posted @ 2016-03-29 17:12  117208  阅读(237)  评论(0编辑  收藏  举报