zoukankan      html  css  js  c++  java
  • 洛谷P4219 大融合

    LCT新姿势:维护子树信息。

    不能带修,子树修改就要toptree了...

    题意:动态加边,求子树大小。

    解:

    维护子树信息只要额外维护虚边连的儿子的信息即可。这里把siz的定义变成子树大小。

    哪里会修改虚边呢?link和access。把这两个函数改一改就行了。

    注意这里link的时候x和y都要make_root,因为修改只能修改根。

      1 #include <cstdio>
      2 #include <algorithm>
      3 
      4 typedef long long LL;
      5 const int N = 100010;
      6 
      7 int fa[N], s[N][2], sum[N], val[N], S[N], Sp;
      8 bool rev[N];
      9 
     10 inline bool no_root(int x) {
     11     return (s[fa[x]][0] == x) || (s[fa[x]][1] == x);
     12 }
     13 
     14 inline void pushup(int x) {
     15     sum[x] = sum[s[x][0]] + sum[s[x][1]] + val[x];
     16     return;
     17 }
     18 
     19 inline void pushdown(int x) {
     20    if(rev[x]) {
     21         if(s[x][0]) {
     22             rev[s[x][0]] ^= 1;
     23         }
     24         if(s[x][1]) {
     25             rev[s[x][1]] ^= 1;
     26         }
     27         std::swap(s[x][0], s[x][1]);
     28         rev[x] = 0;
     29    }
     30    return;
     31 }
     32 
     33 inline void rotate(int x) {
     34     int y = fa[x];
     35     int z = fa[y];
     36     bool f = (s[y][1] == x);
     37 
     38     fa[x] = z;
     39     if(no_root(y)) {
     40         s[z][s[z][1] == y] = x;
     41     }
     42     s[y][f] = s[x][!f];
     43     if(s[x][!f]) {
     44         fa[s[x][!f]] = y;
     45     }
     46     s[x][!f] = y;
     47     fa[y] = x;
     48 
     49     pushup(y);
     50     pushup(x);
     51     return;
     52 }
     53 
     54 inline void splay(int x) {
     55     int y = x;
     56     S[++Sp] = y;
     57     while(no_root(y)) {
     58         y = fa[y];
     59         S[++Sp] = y;
     60     }
     61     while(Sp) {
     62         pushdown(S[Sp]);
     63         Sp--;
     64     }
     65 
     66     y = fa[x];
     67     int z = fa[y];
     68     while(no_root(x)) {
     69         if(no_root(y)) {
     70             (s[z][1] == y) ^ (s[y][1] == x) ?
     71             rotate(x) : rotate(y);
     72         }
     73         rotate(x);
     74         y = fa[x];
     75         z = fa[y];
     76     }
     77     return;
     78 }
     79 
     80 inline void access(int x) {
     81     int y = 0;
     82     while(x) {
     83         splay(x);
     84         val[x] += sum[s[x][1]] - sum[y];
     85         s[x][1] = y;
     86         pushup(x);
     87         y = x;
     88         x = fa[x];
     89     }
     90     return;
     91 }
     92 
     93 inline void make_root(int x) {
     94     access(x);
     95     splay(x);
     96     rev[x] = 1;
     97     return;
     98 }
     99 
    100 inline void link(int x, int y) {
    101     make_root(x);
    102     make_root(y);
    103     fa[x] = y;
    104     val[y] += sum[x];
    105     sum[y] += sum[x];
    106     return;
    107 }
    108 
    109 inline int ask(int x, int r) {
    110     make_root(x);
    111     access(r);
    112     splay(r);
    113     return sum[x];
    114 }
    115 
    116 char str[20];
    117 
    118 int main() {
    119     int n, q;
    120     scanf("%d%d", &n, &q);
    121     for(int i = 1; i <= n; i++) {
    122         val[i] = 1;
    123     }
    124     for(int i = 1, x, y; i <= q; i++) {
    125         scanf("%s%d%d", str, &x, &y);
    126         if(str[0] == 'A') {
    127             link(x, y);
    128         }
    129         else {
    130             int t = ask(x, y);
    131             int tt = ask(y, x);
    132             printf("%lld
    ", 1ll * t * tt);
    133         }
    134     }
    135 
    136     return 0;
    137 }
    AC代码
  • 相关阅读:
    微信小程序支付
    python中 try、except、finally执行顺序
    磁盘设备在 Linux 下的表示方法
    sanic中间件和监听器
    sed命令详解
    awk命令详解
    gd库
    php中计算二维数组中某一元素之和
    Linux SVN 命令详解
    PHP array 操作函数
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10175971.html
Copyright © 2011-2022 走看看