zoukankan      html  css  js  c++  java
  • bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)

    ps:这道题过的人真多啊

    一道树剖的模板题

    (好像还可以用lct做, 然而我并不会

    代码如下

      1 /**************************************************************
      2     Problem: 1036
      3     User: cminus
      4     Language: C++
      5     Result: Accepted
      6     Time:2380 ms
      7     Memory:4052 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <vector>
     12 #include <algorithm>
     13 #include <cstring>
     14 using namespace std;
     15 const int N = 30100;
     16 #define ls (o << 1)
     17 #define rs (ls + 1)
     18   
     19 int n, w[N];
     20 int fa[N], size[N], hs[N], dep[N], top[N], pos[N], tot;
     21 int maxn[N*4], sum[N*4], L, R;
     22 vector < int > edge[N]; 
     23   
     24 inline void dfs1(int u, int d, int f){
     25     dep[u] = d; fa[u] = f; size[u] = 1; hs[u] = -1;
     26     int tmp = 0;
     27     for (int i = 0; i < edge[u].size(); i++){
     28         int &v = edge[u][i];
     29         if (v == f)  continue;
     30         dfs1(v, d + 1, u);
     31         if (size[v] > tmp)
     32             tmp = size[v], hs[u] = v;
     33         size[u] += size[v];
     34     }
     35 }
     36   
     37 inline void dfs2(int u, int t){
     38     top[u] = t, pos[u] = ++tot;
     39     if (hs[u] == -1)    return ;
     40     dfs2(hs[u], t);
     41     for (int i = 0; i < edge[u].size(); i++){
     42         int &v = edge[u][i];
     43         if (v != hs[u] && v != fa[u])
     44             dfs2(v, v);
     45     }
     46 }
     47   
     48 inline int getSum(int o, int l, int r){
     49     if (L <= l && r <= R) return sum[o];
     50     int mid = (l + r) >> 1, ans = 0;
     51     if (L <= mid)    ans += getSum(ls, l, mid);
     52     if (R > mid)     ans += getSum(rs, mid + 1, r);
     53     return ans;
     54 }
     55   
     56 inline int getMax(int o, int l, int r){
     57     if (L <= l && r <= R) return maxn[o];
     58     int mid = l + r >> 1, ans = -0x3f3f3f3f;
     59     if (L <= mid)    ans = max(ans, getMax(ls, l, mid));
     60     if (R > mid) ans = max(ans, getMax(rs, mid + 1, r));
     61     return ans;
     62 }
     63   
     64 inline int getMax(int l, int r){
     65     L = l, R = r;
     66     return  getMax(1, 1, tot);
     67 }
     68   
     69 inline int getSum(int l, int r){
     70     L = l, R = r;
     71     return getSum(1, 1, tot);
     72 }
     73   
     74 inline void queryMax(int u, int v){
     75     int f1 = top[u], f2 = top[v], ans = -0x3f3f3f3f;
     76     while(f1 != f2){
     77         if (dep[f1] < dep[f2])
     78             swap(u, v), swap(f1, f2);
     79         ans = max(ans, getMax(pos[f1], pos[u]));
     80         u = fa[f1]; f1 = top[u];
     81     }
     82     if (dep[u] > dep[v]) swap(u, v);
     83     printf("%d
    ", max(ans, getMax(pos[u], pos[v])));
     84 }
     85   
     86 inline void querySum(int u, int v){
     87     int f1 = top[u], f2 = top[v], ans = 0;
     88     while(f1 != f2){
     89         if (dep[f1] < dep[f2])
     90             swap(u, v), swap(f1, f2);
     91         ans += getSum(pos[f1], pos[u]);
     92         u = fa[f1]; f1 = top[u]; 
     93     }
     94     if (dep[u] > dep[v]) swap(u, v);
     95     printf("%d
    ", ans + getSum(pos[u], pos[v]));
     96 }
     97   
     98 inline void modify(int o, int l, int r, int u, int a){
     99     if(l == r){
    100         sum[o] = maxn[o] = a;
    101         return ;
    102     }
    103     int mid = l + r >> 1;
    104     if (u <= mid)    modify(ls, l, mid, u, a);
    105     else    modify(rs, mid + 1, r, u, a);
    106     sum[o] = sum[ls] + sum[rs];
    107     maxn[o] = max(maxn[ls], maxn[rs]);
    108 }
    109   
    110 int main(){
    111     scanf("%d", &n);
    112     for (int i = 1; i < n; i++){
    113         int x, y; scanf("%d %d", &x, &y);
    114         edge[x].push_back(y);
    115         edge[y].push_back(x);
    116     }
    117     for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
    118     dfs1(1, 1, -1); dfs2(1, 1);
    119     for (int i = 1; i <= n; i++)
    120         modify(1, 1, tot, pos[i], w[i]);
    121     int q;  scanf("%d", &q);
    122     char str[10]; int x, y;
    123     while(q--){
    124         scanf("%s%d%d", str, &x, &y);
    125         if (!strcmp(str, "QMAX"))   queryMax(x, y);
    126         else if (*str == 'C')   modify(1, 1, tot, pos[x], y);
    127         else querySum(x, y);
    128     }
    129     return 0;
    130 } 
    131 
  • 相关阅读:
    ios 数据类型转换 UIImage转换为NSData NSData转换为NSString
    iOS UI 12 block传值
    iOS UI 11 单例
    iOS UI 08 uitableview 自定义cell
    iOS UI 07 uitableviewi3
    iOS UI 07 uitableviewi2
    iOS UI 07 uitableview
    iOS UI 05 传值
    iOS UI 04 轨道和动画
    iOS UI 03 事件和手势
  • 原文地址:https://www.cnblogs.com/cminus/p/7047116.html
Copyright © 2011-2022 走看看