• BZOJ1036 [ZJOI2008]树的统计Count


    再搬运:

    关于树剖的具体内容上,传送门:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html(非常之详细)

    链剖完,线段树上维护的是段最大以及段和即可,操作是点修改。

    但是要注意有负数的情况!!!蒟蒻没看到WA了7、8次。。。蒟蒻就是弱,树剖竟然要写三天。。。买块豆腐去撞死吧

    时间竟然有2500+MS,不过把许多大神踩在下面了,感觉挺好。。

    上代码,感觉写的还不错啊,思路蛮清晰的:

     

      1 #include <cstdlib>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <iostream>
      6 #include <algorithm>
      7  
      8 #define rep(i, n) for (int (i) = 1; (i) <= (n); ++(i))
      9 using namespace std;
     10  
     11 struct edge{
     12     int next, to;
     13 } e[100000];
     14  
     15 struct tree{
     16     int fa, son, size, w, dep, top, where;
     17 } tr[100000];
     18  
     19 struct segment_tree{
     20     int sum, max;
     21 } seg[100000];
     22  
     23 int n, tot, first[100000], size, t, lx, ry;
     24  
     25 void add_Edge(int x, int y){
     26     e[++tot].next = first[x];
     27     first[x] = tot;
     28     e[tot].to = y;
     29 }
     30  
     31 void add_edge(int x, int y){
     32     add_Edge(x, y);
     33     add_Edge(y, x);
     34 }
     35  
     36 void make_tree(int p){
     37     int y;
     38     tr[p].size = 1;
     39     tr[p].son = 0;
     40     for (int x = first[p]; x != 0; x = e[x].next){
     41         y = e[x].to;
     42         if (y != tr[p].fa){
     43             tr[y].dep = tr[p].dep + 1;
     44             tr[y].fa = p;
     45             make_tree(y);
     46             if (tr[p].son == 0 || tr[y].size > tr[tr[p].son].size)
     47                 tr[p].son = y;
     48             tr[p].size += tr[y].size;
     49         }
     50     }
     51 }
     52  
     53 void fill_seg(int i){
     54     if (i >= size){
     55         seg[i].max = -30001;
     56         seg[i].sum = -30001;
     57         return;
     58     }
     59     fill_seg(i * 2);
     60     fill_seg(i * 2 + 1);
     61     seg[i].max = -30001;
     62     seg[i].sum = seg[i * 2].sum * 2;
     63 }
     64  
     65 void change_value(int p, int v){
     66     int x = tr[p].where + size;
     67     seg[x].max = v;
     68     seg[x].sum = v;
     69     while (x > 1){
     70         x >>= 1;
     71         seg[x].max = max(seg[x * 2].max, seg[x * 2 + 1].max);
     72         seg[x].sum = seg[x * 2].sum + seg[x * 2 + 1].sum;
     73     }  
     74 }
     75  
     76 void build_seg(int p){
     77     tr[p].where = ++t;
     78     change_value(p, tr[p].w);
     79 }
     80  
     81 void make_seg(int p){
     82     if (tr[p].size == 1) return;
     83     int s = tr[p].son, y;
     84     tr[s].top = tr[p].top;
     85     build_seg(s);
     86     make_seg(s);
     87     for (int x = first[p]; x != 0; x = e[x].next)
     88         if ((y = e[x].to) != tr[p].fa && y != tr[p].son){
     89             tr[y].top = y;
     90             build_seg(y);
     91             make_seg(y);
     92         }
     93 }
     94  
     95 int seg_max(int p, int l, int r){
     96     if (r < lx || l > ry) return -30001;
     97     if (lx <= l && r <= ry) return seg[p].max;
     98     int m = (l + r) >> 1;
     99     int t1 = seg_max(p * 2, l, m), t2 = seg_max(p * 2 + 1, m + 1, r);
    100     return max(t1, t2);
    101 }
    102  
    103 int tree_max(int x, int y){
    104     if (tr[x].top == tr[y].top){
    105         if (tr[x].dep > tr[y].dep) swap(x, y);
    106         lx = tr[x].where;
    107         ry = tr[y].where;
    108         return seg_max(1, 1, size + 1);
    109     }
    110     if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y);
    111     lx = tr[tr[x].top].where;
    112     ry = tr[x].where;
    113     int t1 = seg_max(1, 1, size + 1), t2 = tree_max(tr[tr[x].top].fa, y);
    114     return max(t1, t2);
    115 }
    116  
    117 int seg_sum(int p, int l, int r){
    118     if (r < lx || l > ry) return 0;
    119     if (lx <= l && r <= ry) return seg[p].sum;
    120     int m = (l + r) >> 1;
    121     int t1 = seg_sum(p * 2, l, m), t2 = seg_sum(p * 2 + 1, m + 1, r);
    122     return t1 + t2;
    123 }
    124  
    125 int tree_sum(int x, int y){
    126     if (tr[x].top == tr[y].top){
    127         if (tr[x].dep > tr[y].dep) swap(x, y);
    128         lx = tr[x].where;
    129         ry = tr[y].where;
    130         return seg_sum(1, 1, size + 1);
    131     }
    132     if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y);
    133     lx = tr[tr[x].top].where;
    134     ry = tr[x].where;
    135     int t1 = seg_sum(1, 1, size + 1) , t2 = tree_sum(tr[tr[x].top].fa, y);
    136     return t1 + t2;
    137 }
    138  
    139 int main(){
    140     scanf("%d", &n);
    141     int x, y;
    142     rep(i, n - 1){
    143         scanf("%d %d", &x, &y);
    144         add_edge(x, y);
    145     }
    146     rep(i, n)
    147         scanf("%d", &tr[i].w);
    148  
    149     for (size = 1; size < n; size <<= 1);
    150     --size;
    151  
    152     tr[1].dep = 1;
    153     make_tree(1);
    154     tr[1].top = 1;
    155     t = 0;
    156     fill_seg(1);
    157     build_seg(1);
    158     make_seg(1);
    159  
    160     int q, a;      
    161     scanf("%d", &q);
    162     char C[10];
    163     while (q--){
    164         scanf("%s %d %d", C, &x, &y);
    165         if (C[0] == 'C')
    166             change_value(x, y); else
    167         if (C[1] == 'M')
    168             printf("%d
    ", tree_max(x, y)); else
    169         if (C[1] == 'S')
    170             printf("%d
    ", tree_sum(x, y));
    171     }
    172     return 0;
    173 }
    View Code
    By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
  • 相关阅读:
    ListenerExecutionFailedException: Listener threw exception
    SpringCloud网关无法加载权限及IP黑名单白名单
    IDEA引入jar但无法导入class
    net.sf.jsqlparser.statement.select.PlainSelect.getGroupBy()Lnet/sf/jsqlparse
    mysql索引
    selenium
    Zuul的容错与回退与Zuul的高可用
    fastjson json转linkedhashmap为null
    微信H5支付签名校验错误
    追踪线程
  • 原文地址:https://www.cnblogs.com/rausen/p/4018038.html
Copyright © 2020-2023  润新知