• BZOJ 1036 树的统计


    Description

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

    Input

    输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    Output

    对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    Sample Input

    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4

    Sample Output

    4
    1
    2
    2
    10
    6
    5
    6
    5
    16

    HINT

     

    Source

     树链剖分大裸题。
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 using namespace std;
      5 #define maxn 30010
      6 #define root 1
      7 int n,next[2*maxn],side[maxn],toit[2*maxn],key[maxn],tot,son[maxn],father[maxn];
      8 int edge[maxn],pos[maxn],top[maxn],dep[maxn],heavy[maxn],ord[maxn];
      9 bool in[maxn];
     10 struct node
     11 {
     12     int l,r;
     13     int best,sum;
     14     int lc,rc;
     15 }seg[4*maxn];
     16  
     17 inline int big(int a,int b){if (a > b)return a;return b;}
     18 inline void add(int,int);
     19 inline void dfs(int,int);
     20 inline void link(int,int);
     21 inline void build(int,int);
     22 inline void change(int,int);
     23 inline void find_best(int,int);
     24 inline void find_sum(int,int);
     25 inline int seg_sum(int,int,int);
     26 inline int seg_best(int,int,int);
     27  
     28 int main()
     29 {
     30     freopen("1036.in","r",stdin);
     31     freopen("1036.out","w",stdout);
     32     scanf("%d",&n);
     33     int i,a,b;
     34     for (i = 1;i<n;i++)
     35     {
     36         scanf("%d %d",&a,&b);
     37         add(a,b); add(b,a);
     38     }
     39     for (i = 1;i<=n;i++)
     40         scanf("%d",key+i);
     41     tot = 0;
     42     dfs(root,1);
     43     tot = 0;
     44     memset(in,0,sizeof(in));
     45     link(root,root);
     46     tot = 1;
     47     build(1,n);
     48     int T;
     49     scanf("%d
    ",&T);
     50     char sign[50];
     51     while (T)
     52     {
     53         T--;
     54         scanf("%s %d %d
    ",sign,&a,&b);
     55         if (sign[0] == 'Q')
     56         {
     57             if (sign[1] == 'M')
     58                 find_best(a,b);
     59             if (sign[1] == 'S')
     60                 find_sum(a,b);
     61         }
     62         else
     63             key[a] = b,change(a,1);
     64          
     65     }
     66     return 0;
     67 }
     68  
     69 inline void add(int a,int b)
     70 {
     71     tot++;
     72     toit[tot] = b;
     73     next[tot] = side[a];
     74     side[a] = tot;
     75 }
     76  
     77 inline void dfs(int a,int deep)
     78 {
     79     in[a] = true; dep[a] = deep;
     80     int u = side[a],v;
     81     son[a] = 1;
     82     while (u != 0)
     83     {
     84         v = toit[u];
     85         if (!in[v])
     86         {
     87             father[v] = a;
     88             edge[++tot] = v;
     89             dfs(v,deep+1);
     90             if (son[heavy[a]] < son[v])
     91                 heavy[a] = v;
     92             son[a] += son[v];
     93         }
     94         u = next[u];
     95     }
     96 }
     97  
     98 inline void link(int a,int high)
     99 {
    100     top[a] = high;
    101     pos[a] = ++tot;
    102     ord[tot] = a;
    103     in[a] = true;
    104     if (heavy[a] != 0)
    105         link(heavy[a],high);
    106     else return;
    107     int u = side[a],v;
    108     while (u != 0)
    109     {
    110         v = toit[u];
    111         if (!in[v])
    112             link(v,v);
    113         u = next[u];
    114     }
    115 }
    116  
    117 inline void build(int l,int r)
    118 {
    119     seg[tot].l = l;
    120     seg[tot].r = r;
    121     if (l == r)
    122     {
    123         seg[tot].best = key[ord[l]];
    124         seg[tot].sum = key[ord[l]];
    125         return;
    126     }
    127     int mid = ((l+r)>>1);
    128     int k = tot;
    129     seg[k].lc = ++tot;
    130     build(l,mid);
    131     seg[k].rc = ++tot;
    132     build(mid+1,r);
    133     seg[k].best = big(seg[seg[k].lc].best,seg[seg[k].rc].best);
    134     seg[k].sum = seg[seg[k].lc].sum+seg[seg[k].rc].sum;
    135 }
    136  
    137 inline void change(int a,int now)
    138 {
    139     if (seg[now].l == seg[now].r)
    140     {
    141         seg[now].best = key[a];
    142         seg[now].sum = key[a];
    143         return;
    144     }
    145     if (seg[seg[now].lc].l<=pos[a]&&seg[seg[now].lc].r>=pos[a])
    146         change(a,seg[now].lc);
    147     else change(a,seg[now].rc);
    148     seg[now].best = big(seg[seg[now].lc].best,seg[seg[now].rc].best);
    149     seg[now].sum = seg[seg[now].lc].sum + seg[seg[now].rc].sum;
    150 }
    151  
    152 inline void find_sum(int a,int b)
    153 {
    154     int sum = 0;
    155     while (top[a] != top[b])
    156     {
    157         if (dep[top[a]]  >= dep[top[b]])
    158         {
    159             sum += seg_sum(pos[top[a]],pos[a],1);
    160             a = father[top[a]];
    161         }       
    162         else
    163         {
    164             sum += seg_sum(pos[top[b]],pos[b],1);
    165             b = father[top[b]];
    166         }
    167     }
    168     if (pos[a] <= pos[b])
    169         sum += seg_sum(pos[a],pos[b],1);
    170     else
    171         sum += seg_sum(pos[b],pos[a],1);
    172     printf("%d
    ",sum);
    173 }
    174  
    175 inline void find_best(int a,int b)
    176 {
    177     int best = -10000000;
    178     while (top[a] != top[b])
    179     {
    180         if (dep[top[a]]  >= dep[top[b]])
    181         {
    182             best = big(best,seg_best(pos[top[a]],pos[a],1));
    183             a = father[top[a]]; 
    184         }       
    185         else
    186         {
    187             best = big(best,seg_best(pos[top[b]],pos[b],1));
    188             b = father[top[b]];
    189         }
    190     }
    191     if (pos[a] <= pos[b])
    192         best = big(best,seg_best(pos[a],pos[b],1));
    193     else
    194         best = big(best,seg_best(pos[b],pos[a],1));
    195     printf("%d
    ",best);
    196 }
    197  
    198 inline int seg_best(int l,int r,int now)
    199 {
    200     if (seg[now].l >=l && seg[now].r <=r)
    201         return seg[now].best;
    202     int ret =-10000000;
    203     int t;
    204     t = seg[now].lc;
    205     if (seg[t].l<=l&&seg[t].r>=l)
    206         ret = big(ret,seg_best(l,r,t));
    207     else if (seg[t].l>=l&&seg[t].l<=r)
    208         ret = big(ret,seg_best(l,r,t));
    209     else if (seg[t].r>=l&&seg[t].r<=r)
    210         ret = big(ret,seg_best(l,r,t));
    211     t = seg[now].rc;
    212     if (seg[t].l<=l&&seg[t].r>=l)
    213         ret = big(ret,seg_best(l,r,t));
    214     else if (seg[t].l>=l&&seg[t].l<=r)
    215         ret = big(ret,seg_best(l,r,t));
    216     else if (seg[t].r>=l&&seg[t].r<=r)
    217         ret = big(ret,seg_best(l,r,t));
    218     return ret;
    219 }
    220  
    221 inline int seg_sum(int l,int r,int now)
    222 {
    223     if (seg[now].l >=l && seg[now].r <=r)
    224         return seg[now].sum;
    225     int ret = 0;
    226     int t;
    227     t = seg[now].lc;
    228     if (seg[t].l<=l&&seg[t].r>=l)
    229         ret += seg_sum(l,r,t);
    230     else if (seg[t].l>=l&&seg[t].l<=r)
    231         ret += seg_sum(l,r,t);
    232     else if (seg[t].r>=l&&seg[t].r<=r)
    233         ret += seg_sum(l,r,t);
    234     t = seg[now].rc;
    235     if (seg[t].l<=l&&seg[t].r>=l)
    236         ret += seg_sum(l,r,t);
    237     else if (seg[t].l>=l&&seg[t].l<=r)
    238         ret += seg_sum(l,r,t);
    239     else if (seg[t].r>=l&&seg[t].r<=r)
    240         ret += seg_sum(l,r,t);
    241     return ret;
    242 }
    View Code
  • 相关阅读:
    Gin 框架的使用
    Beego model 增删改查
    Beego 搭建
    Go 如何快速解决依赖管理问题
    Go 语法基础
    使用vue控制元素显示隐藏
    Vue 刷新页面方式 和页面跳转的方式
    如何让nginx 显示文件夹目录
    Vue(项目配置iview的upload插件上传文件 )+ Python flask 上传文件
    uwsgi 常见配置
  • 原文地址:https://www.cnblogs.com/mmlz/p/4271497.html
Copyright © 2020-2023  润新知