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 }