zoukankan      html  css  js  c++  java
  • BZOJ 2959

    题意

    每个点有各自的权值,要求维护操作:动态加边、动态修改权值、询问在每个点只能经过一次的情况下两点间路程中的最大权值和

    题解

    首先对于一个静态的图,将其缩点,可以得到一棵树,那么两点间询问的答案即为它们之间经过的 $BCC$ 的权值和

    支持动态加边,就需要用到 $LCT$ 去维护 $BCC$

    如果两个点所在 $BCC$ 在不同树上,那么直接连边即可;反之,则说明形成了环,就暴力将这条链拖出来,用选定一个标准节点,用并查集将链上其它节点连到标准节点上,容易证明,这样的复杂度是均摊 $O (log n)$ 的

    查询即修改容易实现,不加赘述

    注意,此题没有删边,所以 $findroot$ 可用另一个并查集代替,不然会 $T$

    代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <map>
      5 
      6 using namespace std;
      7 
      8 typedef long long LL;
      9 
     10 const int MAXN = 15e04 + 10;
     11 
     12 int ances[MAXN];
     13 int find (int p) {
     14     return p == ances[p] ? p : ances[p] = find (ances[p]);
     15 }
     16 int lctanc[MAXN];
     17 int lctfind (int p) {
     18     return p == lctanc[p] ? p : lctanc[p] = lctfind (lctanc[p]);
     19 }
     20 
     21 LL realval[MAXN];
     22 int father[MAXN]= {0};
     23 int son[MAXN][2]= {0};
     24 LL Sum[MAXN]= {0}, value[MAXN]= {0};
     25 int revtag[MAXN]= {0};
     26 
     27 int isroot (int p) {
     28     return son[father[p]][0] != p && son[father[p]][1] != p;
     29 }
     30 int sonbel (int p) {
     31     return son[father[p]][1] == p;
     32 }
     33 void reverse (int p) {
     34     if (! p)
     35         return ;
     36     swap (son[p][0], son[p][1]);
     37     revtag[p] ^= 1;
     38 }
     39 void pushup (int p) {
     40     Sum[p] = Sum[son[p][0]] + Sum[son[p][1]] + value[p];
     41 }
     42 void pushdown (int p) {
     43     if (revtag[p]) {
     44         reverse (son[p][0]), reverse (son[p][1]);
     45         revtag[p] = 0;
     46     }
     47 }
     48 void rotate (int p) {
     49     int fa = father[p], anc = father[fa];
     50     int s = sonbel (p);
     51     son[fa][s] = son[p][s ^ 1];
     52     if (son[fa][s])
     53         father[son[fa][s]] = fa;
     54     if (! isroot (fa))
     55         son[anc][sonbel (fa)] = p;
     56     father[p] = anc;
     57     son[p][s ^ 1] = fa, father[fa] = p;
     58     pushup (fa), pushup (p);
     59 }
     60 int Stack[MAXN];
     61 int top = 0;
     62 void splay (int p) {
     63     top = 0, Stack[++ top] = p;
     64     for (int nd = p; ! isroot (nd); nd = father[nd])
     65         Stack[++ top] = father[nd];
     66     while (top > 0)
     67         pushdown (Stack[top]), top --;
     68     for (int fa = father[p]; ! isroot (p); rotate (p), fa = father[p])
     69         if (! isroot (fa))
     70             sonbel (p) == sonbel (fa) ? rotate (fa) : rotate (p);
     71 }
     72 void Access (int p) {
     73     for (int tp = 0; p; tp = p, p = father[tp] = find (father[p])) // 注意因为有并查集,所以也要同时更新father[tp]
     74         splay (p), son[p][1] = tp, pushup (p);
     75 }
     76 void Makeroot (int p) {
     77     Access (p), splay (p), reverse (p);
     78 }
     79 void Split (int x, int y) {
     80     Makeroot (x);
     81     Access (y), splay (y);
     82 }
     83 void link (int x, int y) {
     84     Makeroot (x);
     85     father[x] = y;
     86     int fx = lctfind (x), fy = lctfind (y);
     87     lctanc[fx] = fy;
     88 }
     89 
     90 void merge (int p, int root) { // 暴力合并
     91     if (! p)
     92         return ;
     93     if (p != root)
     94         ances[p] = root, value[root] += value[p];
     95     merge (son[p][0], root), merge (son[p][1], root);
     96 }
     97 void Add (int x, int y) {
     98     int fx = find (x), fy = find (y);
     99     if (fx == fy)
    100         return ;
    101     if (lctfind (fx) != lctfind (fy)) {
    102         link (fx, fy);
    103         return ;
    104     }
    105     Split (fx, fy);
    106     merge (fy, fy);
    107     son[fy][0] = son[fy][1] = 0;
    108     pushup (fy);
    109 }
    110 void Modify (int x, int val) {
    111     int fx = find (x);
    112     splay (fx);
    113     value[fx] -= realval[x] - val, realval[x] = val;
    114     pushup (fx);
    115 }
    116 LL Query (int x, int y) {
    117     int fx = find (x), fy = find (y);
    118     if (lctfind (fx) != lctfind (fy))
    119         return - 1;
    120     Split (fx, fy);
    121     return Sum[fy];
    122 }
    123 
    124 int N, M;
    125 
    126 int getnum () {
    127     int num = 0;
    128     char ch = getchar ();
    129     int isneg = 0;
    130 
    131     while (! isdigit (ch)) {
    132         if (ch == '-')
    133             isneg = 1;
    134         ch = getchar ();
    135     }
    136     while (isdigit (ch))
    137         num = (num << 3) + (num << 1) + ch - '0', ch = getchar ();
    138 
    139     return isneg ? - num : num;
    140 }
    141 
    142 int answer[MAXN];
    143 int cnt = 0;
    144 int main () {
    145     int N = getnum (), M = getnum ();
    146     for (int i = 1; i <= N; i ++)
    147         Sum[i] = value[i] = realval[i] = getnum (), lctanc[i] = ances[i] = i;
    148     for (int i = 1; i <= M; i ++) {
    149         int type = getnum ();
    150         int x = getnum (), y = getnum ();
    151         if (type == 1)
    152             Add (x, y);
    153         else if (type == 2)
    154             Modify (x, y);
    155         else if (type == 3)
    156             printf ("%lld
    ", Query (x, y));
    157     }
    158 
    159     return 0;
    160 }
    161 
    162 /*
    163 9 31
    164 10 20 30 40 50 60 70 80 90
    165 3 1 2
    166 1 1 3
    167 1 1 2
    168 1 8 9
    169 1 2 4
    170 1 2 5
    171 1 4 6
    172 1 4 7
    173 3 1 8
    174 3 8 8
    175 1 8 9
    176 3 8 8
    177 3 7 5
    178 3 7 3
    179 1 4 1
    180 3 7 5
    181 3 7 3
    182 1 5 7
    183 3 6 5
    184 3 3 6
    185 1 2 4
    186 1 5 5
    187 3 3 6
    188 2 8 180
    189 3 8 8
    190 2 9 190
    191 3 9 9
    192 2 5 150
    193 3 3 6
    194 2 1 210
    195 3 3 6
    196 */
  • 相关阅读:
    让c像python一样可以在命令行写代码并且编译
    动态链接库找不到 : error while loading shared libraries: libgsl.so.0: cannot open shared object file: No such file or directory
    为什么shell中变量赋值不能有空格
    在hyper安装openwrt
    linux扩展lvm磁盘
    docker的基本使用
    tmux与vim主题不一致
    linux centos cli all proxy
    couchDB入门
    tmux复制到windows剪贴板/粘贴板的坑
  • 原文地址:https://www.cnblogs.com/Colythme/p/10187687.html
Copyright © 2011-2022 走看看