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 
  • 相关阅读:
    CentOS下安装vsftpd
    Linux下快速删除大量文件
    /var/spool/postfix/maildrop/ 中有大量的文件
    Linux 查看目录大小及文件数量命令
    windows下体验Redis
    hMailServer SSL 配置
    vmware 安装 Mac OS X 10.9 Mavericks
    提问和看不懂
    C 语言学习 第三次作业总结
    C 语言学习 第二次作业总结
  • 原文地址:https://www.cnblogs.com/cminus/p/7047116.html
Copyright © 2011-2022 走看看