• POJ 3237:Tree(树链剖分)


    http://poj.org/problem?id=3237

    题意:树链剖分。操作有三种:改变一条边的边权,将 a 到 b 的每条边的边权都翻转(即 w[i] = -w[i]),询问 a 到 b 的最大边权。

    思路:一开始没有用区间更新,每次翻转的时候都更新到叶子节点,居然也能过,后来看别人的发现也是可以区间更新的。

    第一种:无区间更新水过

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 using namespace std;
     10 #define N 100010
     11 #define INF -0x7fffffff
     12 #define lson rt<<1, l, m
     13 #define rson rt<<1|1, m + 1, r
     14 struct node
     15 {
     16     int v, w, next;
     17 }edge[N*2];
     18 int top[N], size[N], dep[N], son[N], fa[N], tid[N], time;
     19 int tot, head[N], e[N][3];
     20 int tree[N<<2];
     21 
     22 void init()
     23 {
     24     memset(head, -1, sizeof(head));
     25     memset(son, -1, sizeof(son));
     26     time = tot = 0;
     27 }
     28 
     29 void add(int u, int v, int w)
     30 {
     31     edge[tot].v = v; edge[tot].next = head[u]; edge[tot].w = w; head[u] = tot++;
     32 }
     33 
     34 void dfs1(int u, int f, int d)
     35 {
     36     size[u] = 1;
     37     dep[u] = d;
     38     fa[u] = f;
     39     for(int i = head[u]; ~i; i = edge[i].next) {
     40         int v = edge[i].v;
     41         if(v == f) continue;
     42         dfs1(v, u, d + 1);
     43         size[u] += size[v];
     44         if(son[u] == -1 || size[son[u]] < size[v]) son[u] = v;
     45     }
     46 }
     47 
     48 void dfs2(int u, int tp)
     49 {
     50     top[u] = tp;
     51     tid[u] = ++time;
     52     if(son[u] == -1) return ;
     53     dfs2(son[u], tp);
     54     for(int i = head[u]; ~i; i = edge[i].next) {
     55         int v = edge[i].v;
     56         if(v != son[u] && v != fa[u])
     57             dfs2(v, v);
     58     }
     59 }
     60 
     61 void pushup(int rt)
     62 {
     63     tree[rt] = max(tree[rt<<1], tree[rt<<1|1]);
     64 }
     65 
     66 void build(int rt, int l, int r)
     67 {
     68     tree[rt] = 0;
     69     if(l == r) return ;
     70     int m = (l + r) >> 1;
     71     build(lson); build(rson);
     72 }
     73 
     74 void update(int rt, int l, int r, int id, int w) // 更新边
     75 {
     76     if(l == r && l == id) {
     77         tree[rt] = w;
     78         return ;
     79     }
     80     if(l == r) return ;
     81     int m = (l + r) >> 1;
     82     if(id <= m) update(lson, id, w);
     83     else update(rson, id, w);
     84     pushup(rt);
     85 }
     86 
     87 void Update(int rt, int l, int r, int L, int R) // 翻转值
     88 {
     89     if(l == r && L <= l && r <= R) {
     90         tree[rt] = -tree[rt];
     91         return ;
     92     }
     93     if(l == r) return ;
     94     int m = (l + r) >> 1;
     95     if(L <= m) Update(lson, L, R);
     96     if(R > m) Update(rson, L, R);
     97     pushup(rt);
     98 }
     99 
    100 int query(int rt, int l, int r, int L, int R)
    101 {
    102     int ans = INF;
    103     if(L <= l && r <= R) {
    104         ans = max(ans, tree[rt]);
    105         return ans;
    106     }
    107     int m = (l + r) >> 1;
    108     if(L <= m) ans = max(ans, query(lson, L, R));
    109     if(m < R) ans = max(ans, query(rson, L, R));
    110     return ans;
    111 }
    112 
    113 int change(int u, int v) // 查询 (u, v) 最长距离
    114 {
    115     int ans = INF;
    116     while(top[u] != top[v]) {
    117         if(dep[top[u]] < dep[top[v]]) swap(u, v);
    118         ans = max(ans, query(1, 1, time, tid[top[u]], tid[u]));
    119         u = fa[top[u]];
    120     }
    121     if(u == v) return ans;
    122     if(dep[u] > dep[v]) swap(u, v);
    123     ans = max(ans, query(1, 1, time, tid[son[u]], tid[v]));
    124     return ans;
    125 }
    126 
    127 void uuu(int u, int v) // 将值翻转
    128 {
    129     while(top[u] != top[v]) {
    130         if(dep[top[u]] < dep[top[v]]) swap(u, v);
    131         Update(1, 1, time, tid[top[u]], tid[u]);
    132         u = fa[top[u]];
    133     }
    134     if(u == v) return ;
    135     if(dep[u] > dep[v]) swap(u, v);
    136     Update(1, 1, time, tid[son[u]], tid[v]);
    137 }
    138 
    139 void debug()
    140 {
    141     printf("debug *************
    ");
    142     printf("%d
    ", time);
    143     for(int i = 0; i <= time; i++) {
    144         printf("%d, ", top[i]);
    145     }
    146     puts("");
    147 }
    148 
    149 int main()
    150 {
    151     int t;
    152     scanf("%d", &t);
    153     while(t--) {
    154         int n;
    155         scanf("%d", &n);
    156         init();
    157         for(int i = 1; i < n; i++) {
    158             scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]);
    159             add(e[i][0], e[i][1], e[i][2]);
    160             add(e[i][1], e[i][0], e[i][2]);
    161         }
    162         dfs1(1, 1, 1);
    163         dfs2(1, 1);
    164         build(1, 1, time);
    165         for(int i = 1; i < n; i++) {
    166             if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0], e[i][1]);
    167             update(1, 1, time, tid[e[i][1]], e[i][2]);
    168         }
    169 //        for(int i = 1; i <= n; i++) printf("tid[%d] :%d
    ", i, tid[i]);
    170         char s[10];
    171         int a, b;
    172         while(scanf("%s", s) == 1) {
    173             if(s[0] == 'D') break;
    174             scanf("%d%d", &a, &b);
    175             if(s[0] == 'Q') {
    176 //                puts("");
    177                 printf("%d
    ", change(a, b));
    178 //                puts("");
    179             } else if(s[0] == 'N') {
    180                 uuu(a, b);
    181             } else {
    182                 update(1, 1, time, tid[e[a][1]], b);
    183             }
    184         }
    185     }
    186     return 0;
    187 }

    第二种:区间更新

    比上一种快了一倍的时间。就是记录一个最大值和最小值,在翻转的时候,最大值 = -最小值, 最小值 = -最大值,每次标记取反。这样可以快速求出来。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 using namespace std;
     10 #define N 100010
     11 #define INF 0x7fffffff
     12 #define lson rt<<1, l, m
     13 #define rson rt<<1|1, m + 1, r
     14 struct node
     15 {
     16     int v, w, next;
     17 }edge[N*2];
     18 int top[N], size[N], dep[N], son[N], fa[N], tid[N], time;
     19 int tot, head[N], e[N][3];
     20 int col[N<<2], Min[N<<2], Max[N<<2];
     21 
     22 void init()
     23 {
     24     memset(head, -1, sizeof(head));
     25     memset(son, -1, sizeof(son));
     26     time = tot = 0;
     27 }
     28 
     29 void add(int u, int v, int w)
     30 {
     31     edge[tot].v = v; edge[tot].next = head[u]; edge[tot].w = w; head[u] = tot++;
     32 }
     33 
     34 void dfs1(int u, int f, int d)
     35 {
     36     size[u] = 1;
     37     dep[u] = d;
     38     fa[u] = f;
     39     for(int i = head[u]; ~i; i = edge[i].next) {
     40         int v = edge[i].v;
     41         if(v == f) continue;
     42         dfs1(v, u, d + 1);
     43         size[u] += size[v];
     44         if(son[u] == -1 || size[son[u]] < size[v]) son[u] = v;
     45     }
     46 }
     47 
     48 void dfs2(int u, int tp)
     49 {
     50     top[u] = tp;
     51     tid[u] = ++time;
     52     if(son[u] == -1) return ;
     53     dfs2(son[u], tp);
     54     for(int i = head[u]; ~i; i = edge[i].next) {
     55         int v = edge[i].v;
     56         if(v != son[u] && v != fa[u])
     57             dfs2(v, v);
     58     }
     59 }
     60 
     61 void pushup(int rt)
     62 {
     63     Min[rt] = min(Min[rt<<1], Min[rt<<1|1]);
     64     Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
     65 }
     66 
     67 void pushdown(int rt)
     68 {
     69     int tmp;
     70     if(col[rt]) {
     71         tmp = -Max[rt<<1];
     72         Max[rt<<1] = -Min[rt<<1];
     73         Min[rt<<1] = tmp;
     74 
     75         tmp = -Max[rt<<1|1];
     76         Max[rt<<1|1] = -Min[rt<<1|1];
     77         Min[rt<<1|1] = tmp;
     78 
     79         col[rt<<1] ^= 1;
     80         col[rt<<1|1] ^= 1;
     81         col[rt] ^= 1;
     82     }
     83 }
     84 
     85 void build(int rt, int l, int r)
     86 {
     87     Min[rt] = INF;
     88     Max[rt] = -INF;
     89     col[rt] = 0;
     90     if(l == r) return ;
     91     int m = (l + r) >> 1;
     92     build(lson); build(rson);
     93 }
     94 
     95 void update(int rt, int l, int r, int id, int w) // 更新边
     96 {
     97     if(l == r && l == id) {
     98         Min[rt] = Max[rt] = w;
     99         return ;
    100     }
    101     pushdown(rt);
    102     int m = (l + r) >> 1;
    103     if(id <= m) update(lson, id, w);
    104     else update(rson, id, w);
    105     pushup(rt);
    106 }
    107 
    108 void Update(int rt, int l, int r, int L, int R) // 翻转值
    109 {
    110     int tmp;
    111     if(L <= l && r <= R) {
    112         tmp = -Max[rt];
    113         Max[rt] = -Min[rt];
    114         Min[rt] = tmp;
    115         col[rt] ^= 1;
    116         return ;
    117     }
    118     pushdown(rt);
    119     int m = (l + r) >> 1;
    120     if(L <= m) Update(lson, L, R);
    121     if(R > m) Update(rson, L, R);
    122     pushup(rt);
    123 }
    124 
    125 int query(int rt, int l, int r, int L, int R)
    126 {
    127     int ans = -INF;
    128     if(L <= l && r <= R) {
    129         ans = max(ans, Max[rt]);
    130         return ans;
    131     }
    132     pushdown(rt);
    133     int m = (l + r) >> 1;
    134     if(L <= m) ans = max(ans, query(lson, L, R));
    135     if(m < R) ans = max(ans, query(rson, L, R));
    136     return ans;
    137 }
    138 
    139 int change(int u, int v) // 查询 (u, v) 最长距离
    140 {
    141     int ans = -INF;
    142     while(top[u] != top[v]) {
    143         if(dep[top[u]] < dep[top[v]]) swap(u, v);
    144         ans = max(ans, query(1, 1, time, tid[top[u]], tid[u]));
    145         u = fa[top[u]];
    146     }
    147     if(u == v) return ans;
    148     if(dep[u] > dep[v]) swap(u, v);
    149     ans = max(ans, query(1, 1, time, tid[son[u]], tid[v]));
    150     return ans;
    151 }
    152 
    153 void uuu(int u, int v) // 将值翻转
    154 {
    155     while(top[u] != top[v]) {
    156         if(dep[top[u]] < dep[top[v]]) swap(u, v);
    157         Update(1, 1, time, tid[top[u]], tid[u]);
    158         u = fa[top[u]];
    159     }
    160     if(u == v) return ;
    161     if(dep[u] > dep[v]) swap(u, v);
    162     Update(1, 1, time, tid[son[u]], tid[v]);
    163 }
    164 
    165 int main()
    166 {
    167     int t;
    168     scanf("%d", &t);
    169     while(t--) {
    170         int n;
    171         scanf("%d", &n);
    172         init();
    173         for(int i = 1; i < n; i++) {
    174             scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]);
    175             add(e[i][0], e[i][1], e[i][2]);
    176             add(e[i][1], e[i][0], e[i][2]);
    177         }
    178         dfs1(1, 1, 1);
    179         dfs2(1, 1);
    180         build(1, 1, time);
    181         for(int i = 1; i < n; i++) {
    182             if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0], e[i][1]);
    183             update(1, 1, time, tid[e[i][1]], e[i][2]);
    184         }
    185         char s[10];
    186         int a, b;
    187         while(scanf("%s", s) == 1) {
    188             if(s[0] == 'D') break;
    189             scanf("%d%d", &a, &b);
    190             if(s[0] == 'Q') {
    191                 printf("%d
    ", change(a, b));
    192             } else if(s[0] == 'N') {
    193                 uuu(a, b);
    194             } else {
    195                 update(1, 1, time, tid[e[a][1]], b);
    196             }
    197         }
    198     }
    199     return 0;
    200 }
    201 
    202 /*
    203 1
    204 
    205 3
    206 1 2 1
    207 2 3 2
    208 QUERY 1 2
    209 CHANGE 1 3
    210 QUERY 1 2
    211 NEGATE 1 3
    212 QUERY 1 3
    213 DONE
    214 */
  • 相关阅读:
    C++探究transform算法
    C++探究foreach算法
    C++ MFC棋牌类小游戏day6
    C++ MFC棋牌类小游戏day5
    C++ MFC棋牌类小游戏day4
    C++ MFC棋牌类小游戏day3
    MFC 字体
    C++ MFC棋牌类小游戏day2
    第三章 使用属性升级MyBank
    第二章 C#语法快速热身
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6016665.html
Copyright © 2020-2023  润新知