【bzoj 3306】树

Description

给定一棵大小为 n 的有根点权树,支持以下操作: 
  • 换根 
  • 修改点权  
     • 查询子树最小值 

 

Input

  第一行两个整数 n, Q ,分别表示树的大小和操作数。 
  接下来n行,每行两个整数f,v,第i+1行的两个数表示点i的父亲和点i的权。保证f < i。如 果f = 0,那么i为根。输入数据保证只有i = 1时,f = 0。 
  接下来 m 行,为以下格式中的一种: 
  • V x y表示把点x的权改为y 
  • E x 表示把有根树的根改为点 x 
  • Q x 表示查询点 x 的子树最小值 

 

Output

  对于每个 Q ,输出子树最小值。 

 

Sample Input


3 7
0 1
1 2
1 3
Q 1
V 1 6
Q 1
V 2 5
Q 1
V 3 4
Q 1


Sample Output



1
2
3
4

HINT

 

  对于 100% 的数据:n, Q ≤ 10^5。

题解:

  蛮裸的一道题(但我线段树打错,一路狂wa……)

  跑dfs序,用线段树维护dfs序区间最值。对于x与root的关系:

1.x==root ,全局最小

2.x为root祖先节点,找到x的某个包含root的儿子,查询除去这个儿子以为的全局最值

3.其他情况下,直接查询x子树最值。

代码:

  1 #include<cstdio>
  2 inline int min(int a,int b){return a<b?a:b;}
  3 const int N=(int )1e5+10;
  4 inline int read(){
  5     int s=0,k=1;char ch=getchar();
  6     while(ch<'0'||ch>'9')   k=ch=='-'?-1:k,ch=getchar();
  7     while(ch>47&&ch<='9')   s=s*10+(ch^48),ch=getchar();
  8     return s*k;
  9 }
 10 int n,Q;
 11 struct edges{
 12     int v;edges *last;
 13 }edge[N],*head[N];int cnt;
 14 inline void push(int u,int v){
 15     edge[++cnt]=(edges){v,head[u]};head[u]=edge+cnt;
 16 }
 17 struct Tree{
 18     int val;Tree *son[2];
 19     Tree(){
 20         son[0]=son[1]=NULL;
 21     }
 22 }tree[N<<2],*root;
 23 int val[N];
 24 int rt;
 25 int f[18][N],deep[N];
 26 int l[N],r[N],re[N];
 27 int num;
 28 inline void dfs(int x){
 29     l[x]=++num;
 30     re[num]=x;
 31     for(int i=1;(1<<i)<=deep[x];i++)
 32         f[i][x]=f[i-1][f[i-1][x]];
 33     for(edges *i=head[x];i;i=i->last){
 34         deep[i->v]=deep[x]+1;
 35         f[0][i->v]=x;
 36         dfs(i->v);
 37     }
 38     r[x]=num;
 39 }
 40 inline int LCA(int x,int y){
 41     if(deep[x]<deep[y]) x^=y^=x^=y;
 42     int t=deep[x]-deep[y];
 43     for(int i=0;t;i++)  if(t&(1<<i)){
 44         t^=(1<<i);
 45         x=f[i][x];
 46     }
 47     if(x==y)    return x;
 48     for(int i=16;i>=0;i--){
 49         if(f[i][x]!=f[i][y])
 50             x=f[i][x],y=f[i][y];
 51     }return f[0][x];
 52 }   
 53 inline void build(Tree *&u,int l,int r){
 54     u=tree+cnt;
 55     cnt++;
 56     if(l==r){
 57         u->val=val[re[l]];return ;
 58     }
 59     int mid=l+r>>1;
 60     build(u->son[0],l,mid);
 61     build(u->son[1],mid+1,r);
 62     u->val=min(u->son[0]->val,u->son[1]->val);
 63     //printf("l=%d r=%d val=%d son[0]=%d son[1]=%d\n",l,r,u->val,u->son[0]->val,u->son[1]->val);
 64 }
 65 
 66 inline void add(Tree *u,int l,int r,int x,int w){
 67     if(l==r){
 68         u->val=w;return ;
 69     }
 70     int mid=l+r>>1;
 71     if(x>mid)   add(u->son[1],mid+1,r,x,w);
 72     else    add(u->son[0],l,mid,x,w);
 73      u->val=min(u->son[0]->val,u->son[1]->val);
 74 }
 75 
 76 inline int query(Tree *u,int l,int r,int x,int y){
 77     if(x>y) return 0x7fffffff;
 78     if(x<=l&&r<=y){
 79         return u->val;
 80     }
 81     int mid=l+r>>1;
 82     if(x>mid)   return query(u->son[1],mid+1,r,x,y);
 83     else    if(y<=mid)  return query(u->son[0],l,mid,x,y);
 84     return min(query(u->son[0],l,mid,x,y),query(u->son[1],mid+1,r,x,y));   
 85 }
 86 int main(){
 87     n=read(),Q=read();
 88     for(int i=1;i<=n;i++){
 89         int x=read();
 90         if(x==0)    rt=i;
 91         val[i]=read();push(x,i);
 92     }
 93     dfs(rt);
 94     cnt=0;
 95     build(root,1,n);
 96     char op[4];
 97     while(Q--){
 98         scanf("%s",op);
 99         if(op[0]=='V'){
100             int x=read(),y=read();
101             add(root,1,n,l[x],y);
102         }else   if(op[0]=='E'){
103             int x=read();
104             rt=x;
105         }else{
106             int x=read();
107             if(rt==x){
108                 printf("%d\n",root->val);
109                 continue;
110             }
111             if(l[x]<=l[rt]&&r[x]>=r[rt]){
112                 int y=rt;
113                 int t=deep[rt]-deep[x]-1;
114                 for(int i=0;t;i++)if(t&(1<<i)){
115                     t^=1<<i;
116                     y=f[i][y];
117                 }
118                 printf("%d\n",min(query(root,1,n,1,l[y]-1),query(root,1,n,r[y]+1,n)));
119             }else{
120                 printf("%d\n",query(root,1,n,l[x],r[x]));
121             }
122         }
123     }
124 }
125 /*
126 3 7
127 0 1
128 1 2
129 1 3
130 Q 1
131 V 1 6
132 Q 1
133 V 2 5
134 Q 1
135 V 3 4
136 Q 1
137 */

 

posted @ 2017-08-13 20:50  Troywar  阅读(308)  评论(0编辑  收藏  举报