zoukankan      html  css  js  c++  java
  • hdu 3966 Aragorn's Story : 树链剖分 O(nlogn)建树 O((logn)²)修改与查询

      1 /**
      2 problem: http://acm.hdu.edu.cn/showproblem.php?pid=3966
      3 裸板
      4 **/
      5 #include<stdio.h>
      6 #include<stdlib.h>
      7 #include<string.h>
      8 #include<vector>
      9 using namespace std;
     10 
     11 const int MAXN = 500005;
     12 
     13 template <typename T>
     14 class SegmentTree {
     15 private:
     16     struct Node {
     17         int left, right;
     18         T sum, lazy;
     19     } node[MAXN << 2];
     20     T data[MAXN];
     21     void pushUp(int root) {
     22         node[root].sum = node[root << 1].sum + node[root << 1 | 1].sum;
     23     }
     24     void pushDown(int root) {
     25         if(node[root].left == node[root].right) return;
     26         int lson = root << 1;
     27         int rson = root << 1 | 1;
     28         node[lson].sum += node[root].lazy * (node[lson].right - node[lson].left + 1);
     29         node[rson].sum += node[root].lazy * (node[rson].right - node[rson].left + 1);
     30         node[lson].lazy += node[root].lazy;
     31         node[rson].lazy += node[root].lazy;
     32         node[root].lazy = 0;
     33     }
     34 public:
     35     void build(int left, int right, int root = 1) {
     36         node[root].left = left;
     37         node[root].right = right;
     38         node[root].lazy = 0;
     39         if(left == right) {
     40             node[root].sum = data[left];
     41         } else {
     42             int mid = (left + right) >> 1;
     43             build(left, mid, root << 1);
     44             build(mid + 1, right, root << 1 | 1);
     45             pushUp(root);
     46         }
     47     }
     48     void update(int left, int right, T value, int root = 1) {
     49         int lson = root << 1;
     50         int rson = root << 1 | 1;
     51         node[root].sum += value * (right - left + 1);
     52         if(node[root].left == left && node[root].right == right) {
     53             node[root].lazy += value;
     54             return ;
     55         }
     56         if(left >= node[rson].left) {
     57             update(left, right, value, rson);
     58         } else if(right <= node[lson].right) {
     59             update(left, right, value, lson);
     60         } else {
     61             update(left, node[lson].right, value, lson);
     62             update(node[rson].left, right, value, rson);
     63         }
     64     }
     65     T query(int left, int right, int root = 1) {
     66         int lson = root << 1;
     67         int rson = root << 1 | 1;
     68         if(node[root].lazy) pushDown(root);
     69         if(node[root].left == left && node[root].right == right) {
     70             return node[root].sum;
     71         }
     72         if(left >= node[rson].left) {
     73             return query(left, right, rson);
     74         } else if(right <= node[lson].right) {
     75             return query(left, right, lson);
     76         } else {
     77             return query(left, node[lson].right, lson) + query(node[rson].left, right, rson);
     78         }
     79     }
     80     void clear(int n, const vector<int> &d) {
     81         for(int i = 1; i <= n; i ++) {
     82             this->data[i] = d[i];
     83         }
     84         build(1, n);
     85     }
     86 };
     87 
     88 template <typename T>
     89 class TreeToLink {
     90 private:
     91     struct Point {
     92         int size, son, depth, father, top, newId;
     93         T data;
     94     } point[MAXN];
     95     struct Edge {
     96         int to, next;
     97     } edge[MAXN << 1];
     98     int oldId[MAXN], first[MAXN], sign, sumOfPoint, cnt;
     99     SegmentTree<T> st;
    100     void dfs1(int u, int father = 0, int depth = 1) {
    101         point[u].depth = depth;
    102         point[u].father = father;
    103         point[u].size = 1;
    104         int maxson = -1;
    105         for(int i = first[u]; i != -1; i = edge[i].next) {
    106             int to = edge[i].to;
    107             if(to == father) continue;
    108             dfs1(to, u, depth + 1);
    109             point[u].size += point[to].size;
    110             if(point[to].size > maxson) {
    111                 point[u].son = to;
    112                 maxson = point[to].size;
    113             }
    114         }
    115     }
    116     void dfs2(int u, int top) {
    117         point[u].newId = ++cnt;
    118         oldId[cnt] = u;
    119         point[u].top = top;
    120         if(point[u].son == -1) {
    121             return ;
    122         }
    123         dfs2(point[u].son, top);
    124         for(int i = first[u]; i != -1; i = edge[i].next) {
    125             int to = edge[i].to;
    126             if(to == point[u].son || to == point[u].father) continue;
    127             dfs2(to, to);
    128         }
    129     }
    130 public:
    131     void clear(int n) {
    132         sumOfPoint = n;
    133         sign = 0;
    134         cnt = 0;
    135         for(int i = 1; i <= n; i ++) {
    136             first[i] = -1;
    137             point[i].son = -1;
    138             scanf("%d", &point[i].data);
    139         }
    140     }
    141     void addEdgeOneWay(int u, int v) {
    142         edge[sign].to = v;
    143         edge[sign].next = first[u];
    144         first[u] = sign ++;
    145     }
    146     void addEdgeTwoWay(int u, int v) {
    147         addEdgeOneWay(u, v);
    148         addEdgeOneWay(v, u);
    149     }
    150     void preWork(int x = 1) {
    151         dfs1(x);
    152         dfs2(x, x);
    153         vector<int> data(sumOfPoint + 1);
    154         for(int i = 1; i <= sumOfPoint; i ++) {
    155             data[i] = point[oldId[i]].data;
    156         }
    157         st.clear(sumOfPoint, data);
    158     }
    159     void updatePath(int x, int y, T z){
    160         while(point[x].top != point[y].top){
    161             if(point[point[x].top].depth < point[point[y].top].depth)
    162                 swap(x, y);
    163             st.update(point[point[x].top].newId, point[x].newId, z);
    164             x = point[point[x].top].father;
    165         }
    166         if(point[x].depth > point[y].depth)
    167             swap(x, y);
    168         st.update(point[x].newId, point[y].newId, z);
    169     }
    170     T queryPath(int x, int y){
    171         T ans = 0;
    172         while(point[x].top != point[y].top){
    173             if(point[point[x].top].depth < point[point[y].top].depth)
    174                 swap(x, y);
    175             ans += st.query(point[point[x].top].newId, point[x].newId);
    176             x = point[point[x].top].father;
    177         }
    178         if(point[x].depth > point[y].depth)
    179             swap(x, y);
    180         ans += st.query(point[x].newId, point[y].newId);
    181         return ans;
    182     }
    183     void updateSon(int x, T z){
    184         st.update(point[x].newId, point[x].newId + point[x].size - 1, z);
    185     }
    186     T querySon(int x){
    187         return st.query(point[x].newId, point[x].newId + point[x].size - 1);
    188     }
    189     T queryPoint(int x) {
    190         return queryPath(x, x);
    191     }
    192     void updatePoint(int x, T z) {
    193         updatePath(x, x, z);
    194     }
    195 };
    196 
    197 class Solution {
    198 private:
    199     int n, m, p;
    200     TreeToLink<int> ttl;
    201 public:
    202     void solve() {
    203         while(~scanf("%d%d%d", &n, &m, &p)){
    204             ttl.clear(n);
    205             for(int i = 0, a, b; i < m; i ++) {
    206                 scanf("%d%d", &a, &b);
    207                 ttl.addEdgeTwoWay(a, b);
    208             }
    209             ttl.preWork();
    210             while(p --) {
    211                 char opt;
    212                 int a, b, c;
    213                 scanf(" %c%d", &opt, &a);
    214                 if(opt == 'I') {
    215                     scanf("%d%d", &b, &c);
    216                     ttl.updatePath(a, b, c);
    217                 } else if(opt == 'D') {
    218                     scanf("%d%d", &b, &c);
    219                     ttl.updatePath(a, b, -c);
    220                 } else if(opt == 'Q') {
    221                     printf("%d
    ", ttl.queryPoint(a));
    222                 }
    223             }
    224         }
    225     }
    226 } DarkScoCu;
    227 
    228 int main() {
    229     DarkScoCu.solve();
    230     return 0;
    231 }
  • 相关阅读:
    MethodNotAllowedHttpException
    laravel项目return back()->withErrors($validator)或return back()->with('errors','原密码错误!')在前台原密码错误的情况下不能正确显示错误信息,变成报错!
    laravel加入验证码类几种方法 && Laravel引入第三方库的方法
    使用Git命令从Github下载代码仓库
    4-ESP8266 SDK开发基础入门篇--串口
    2-STM32+W5500+GPRS物联网开发基础篇-基础篇学习的内容
    3-ESP8266 SDK开发基础入门篇--点亮一个灯
    2-ESP8266 SDK开发基础入门篇--非RTOS版与RTOS版
    1-ESP8266 SDK开发基础入门篇--开发环境搭建
    11-网页,网站,微信公众号基础入门(配置自己的微信公众号,添加一个按钮)
  • 原文地址:https://www.cnblogs.com/DarkScoCu/p/10699145.html
Copyright © 2011-2022 走看看