zoukankan      html  css  js  c++  java
  • 【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
    ",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
    ",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
    ",min(query(root,1,n,1,l[y]-1),query(root,1,n,r[y]+1,n)));
    119             }else{
    120                 printf("%d
    ",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 */
  • 相关阅读:
    KVM切换声音关闭
    tmux 快捷键
    arp绑定网关MAC地址错误
    javascript的字符串模板
    cheerio, dom操作模块
    footable动态载入数据
    node-js访问rest api的方法
    重装eclipse要做的事
    爬虫(三):对requests、xpath模块
    Java-基础篇(类和对象)
  • 原文地址:https://www.cnblogs.com/Troywar/p/7354729.html
Copyright © 2011-2022 走看看