• (树链剖分+线段树)POJ


    前言:

    一直听说树链剖分-树链剖分,现在见识一下,,,感觉不是很难0.0

    看了一下kuangbin模板基本秒懂

    对于点,按重边优先给予每个点一个编号,对于一条重链上的点,编号则是连续的,将所有编号映射到线段树上,即可进行一切区间操作。

    对于边的处理,我们将所有边对应到这条边节点更深的那个点上即可。

    如果需要的操作只有求和,和单点更新/区间更新,直接用树状数组也是可以的,可能常数大那么一点点。

    如果还需要更加强大的操作,显然用splay树维护也是可以的。。

    比如树链上所有权值翻转等等。。不过,,这样差不多应该就快到LCT了。。虽然自己不会。。

    不过过几天就该看了。

    题意:

    一棵树,每条边有一个权值,三种操作:

    1、改变第i条边权值为v

    2、将节点a到节点b之间的边权值取反

    3、查询a到b之间最大的边权值

    分析:

    显然就是普通的树链剖分和线段树

    但是要记得pushdown,

    而对于lazy标记rev,当传下去的时候,不应该直接赋值为1或者0,而应该直接取反,用异或即可。

    代码:

      1 #include <math.h>
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <time.h>
      6 #include <algorithm>
      7 #include <iostream>
      8 #include <map>
      9 #include <queue>
     10 #include <set>
     11 #include <string>
     12 #include <vector>
     13 using namespace std;
     14 
     15 const int maxn = 100010;
     16 const int inf = 0x3f3f3f3f;
     17 
     18 struct Edge {
     19     int to, next;
     20 } edge[maxn << 1];
     21 
     22 int head[maxn], tot;
     23 int top[maxn];
     24 int fa[maxn];
     25 int deep[maxn];
     26 int num[maxn];
     27 int p[maxn];
     28 int fp[maxn];
     29 int son[maxn];
     30 int pos;
     31 
     32 void init() {
     33     tot = 0;
     34     memset(head, -1, sizeof head);
     35     pos = 0;
     36     memset(son, -1, sizeof son);
     37 }
     38 
     39 void addedge(int u, int v) {
     40     edge[tot].to = v;
     41     edge[tot].next = head[u];
     42     head[u] = tot++;
     43 }
     44 void dfs1(int u, int pre, int d) {
     45     deep[u] = d;
     46     fa[u] = pre;
     47     num[u] = 1;
     48     for (int i = head[u]; i != -1; i = edge[i].next) {
     49         int v = edge[i].to;
     50         if (v != pre) {
     51             dfs1(v, u, d + 1);
     52             num[u] += num[v];
     53             if (son[u] == -1 || num[v] > num[son[u]]) son[u] = v;
     54         }
     55     }
     56 }
     57 
     58 void getpos(int u, int sp) {
     59     top[u] = sp;
     60     p[u] = pos++;
     61     fp[p[u]] = u;
     62     if (son[u] == -1) return;
     63     getpos(son[u], sp);
     64     for (int i = head[u]; i != -1; i = edge[i].next) {
     65         int v = edge[i].to;
     66         if (v != son[u] && v != fa[u]) getpos(v, v);
     67     }
     68 }
     69 
     70 struct Node {
     71     int left, right, maxs, mins;
     72     int rev;
     73 } node[maxn << 2];
     74 
     75 void build(int n, int left, int right) {
     76     node[n].left = left;
     77     node[n].right = right;
     78     node[n].maxs = 0;
     79     node[n].mins = 0;
     80     node[n].rev = 0;
     81     if (left == right) return;
     82     int mid = (left + right) >> 1;
     83     build(n << 1, left, mid);
     84     build(n << 1 | 1, mid + 1, right);
     85 }
     86 
     87 void push_up(int n) {
     88     node[n].maxs = max(node[n << 1].maxs, node[n << 1 | 1].maxs);
     89     node[n].mins = min(node[n << 1].mins, node[n << 1 | 1].mins);
     90 }
     91 
     92 void push_down(int n) {
     93     if (node[n].left == node[n].right) return;
     94     if (node[n].rev) {
     95         node[n << 1].rev ^= 1;
     96         node[n << 1 | 1].rev ^= 1;
     97         swap(node[n << 1].mins, node[n << 1].maxs);
     98         node[n << 1].mins *= -1;
     99         node[n << 1].maxs *= -1;
    100         swap(node[n << 1 | 1].mins, node[n << 1 | 1].maxs);
    101         node[n << 1 | 1].mins *= -1;
    102         node[n << 1 | 1].maxs *= -1;
    103         node[n].rev = 0;
    104     }
    105 }
    106 
    107 void update(int n, int pos, int val) {
    108     if (node[n].left == node[n].right) {
    109         node[n].maxs = val;
    110         node[n].mins = val;
    111         node[n].rev = 0;
    112         return;
    113     }
    114     push_down(n);
    115     int mid = (node[n].left + node[n].right) >> 1;
    116     if (pos <= mid)
    117         update(n << 1, pos, val);
    118     else
    119         update(n << 1 | 1, pos, val);
    120     push_up(n);
    121 }
    122 
    123 void Rev(int n, int left, int right) {
    124     if (left <= node[n].left && node[n].right <= right) {
    125         node[n].rev ^= 1;
    126         swap(node[n].mins, node[n].maxs);
    127         node[n].mins *= -1;
    128         node[n].maxs *= -1;
    129         return;
    130     }
    131     push_down(n);
    132     int mid = (node[n].left + node[n].right) >> 1;
    133     if (mid >= left) Rev(n << 1, left, right);
    134     if (mid < right) Rev(n << 1 | 1, left, right);
    135     push_up(n);
    136 }
    137 
    138 int query(int n, int left, int right) {
    139     if (left <= node[n].left && node[n].right <= right) {
    140         return node[n].maxs;
    141     }
    142     push_down(n);
    143     int mid = (node[n].left + node[n].right) >> 1;
    144     int maxs = -inf;
    145     if (mid >= left) maxs = max(maxs, query(n << 1, left, right));
    146     if (mid < right) maxs = max(maxs, query(n << 1 | 1, left, right));
    147     push_up(n);
    148     return maxs;
    149 }
    150 
    151 int findMax(int u, int v) {
    152     int f1 = top[u], f2 = top[v];
    153     int tmp = -inf;
    154     while (f1 != f2) {
    155         if (deep[f1] < deep[f2]) {
    156             swap(f1, f2);
    157             swap(u, v);
    158         }
    159         tmp = max(tmp, query(1, p[f1], p[u]));
    160         u = fa[f1];
    161         f1 = top[u];
    162     }
    163     if (u == v) return tmp;
    164     if (deep[u] > deep[v]) swap(u, v);
    165     return max(tmp, query(1, p[son[u]], p[v]));
    166 }
    167 
    168 void Negate(int u, int v) {
    169     int f1 = top[u], f2 = top[v];
    170     while (f1 != f2) {
    171         if (deep[f1] < deep[f2]) {
    172             swap(f1, f2);
    173             swap(u, v);
    174         }
    175         Rev(1, p[f1], p[u]);
    176         u = fa[f1];
    177         f1 = top[u];
    178     }
    179     if (u == v) return;
    180     if (deep[u] > deep[v]) swap(u, v);
    181     Rev(1, p[son[u]], p[v]);
    182 }
    183 
    184 int e[maxn][3];
    185 
    186 int main() {
    187     // freopen("1.out", "w", stdout);
    188     int t;
    189     int n;
    190     scanf("%d", &t);
    191     while (t--) {
    192         init();
    193         scanf("%d", &n);
    194         for (int i = 0; i < n - 1; i++) {
    195             int u, v, c;
    196             scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]);
    197             addedge(e[i][0], e[i][1]);
    198             addedge(e[i][1], e[i][0]);
    199         }
    200         dfs1(1, 0, 0);
    201         getpos(1, 1);
    202         build(1, 0, pos - 1);
    203         for (int i = 0; i < n - 1; i++) {
    204             if (deep[e[i][0]] > deep[e[i][1]]) swap(e[i][0], e[i][1]);
    205             update(1, p[e[i][1]], e[i][2]);
    206         }
    207         char op[10];
    208         int u, v;
    209         while (scanf("%s", op)) {
    210             if (op[0] == 'D') break;
    211             scanf("%d%d", &u, &v);
    212             if (op[0] == 'Q')
    213                 printf("%d
    ", findMax(u, v));
    214             else if (op[0] == 'N') {
    215                 Negate(u, v);
    216             } else {
    217                 update(1, p[e[u - 1][1]], v);
    218             }
    219         }
    220     }
    221     return 0;
    222 }
  • 相关阅读:
    习题10-2 递归求阶乘和(15 分)
    在过滤器中得到模型状态信息
    理解OAuth 2.0
    asp.net mvc 控制器的依赖注入(使用Ninject)
    web.routing 学习
    深度优先和广度优先的基础应用
    数的全排
    C# 表达式树
    C#中RSA的简单使用
    select into 和insert into select
  • 原文地址:https://www.cnblogs.com/tak-fate/p/7190244.html
Copyright © 2020-2023  润新知