zoukankan      html  css  js  c++  java
  • [ZJOI2016]大森林

    (貌似整个代码不能用 $makeroot$ ?是因为是有根树?)

    因为是区间操作,所以可以考虑在区间内与区间外的差异

    对于操作 $1$ ,可以看作一个生成节点包含了到下一个 $1$ 操作之间长出的节点,那么对于一个操作 $l, r$ ,相当于是在 $l$ 处将当前生成节点及其包含的节点整个移植到它更改后的位置,到 $r + 1$ 时再移植回去,所以可以考虑将一个 $1$ 操作分解为两个操作(一个移植,一个移植回去),故可以将所有操作按端点、时间排序(以及同位置修改操作必定在查询操作前,因为可以先把树建完再查询对结果没有影响),扫描一遍即可

    同时,为了方便移植,将每个生成节点看作新建的一个虚点

    对于操作 $0$ ,直接在虚点下 $link$ 即可,因为就算已经建了一些对于当前操作不存在的虚点,也不会对答案造成影响

    对于操作 $2$ ,无法正面在 $LCT$ 上算出两点的距离,故可考虑差分,得到 $Ans = Sum_x + Sum_y - 2 * Sum_{lca}$ ,其中实点贡献为 $1$ ,虚点贡献为 $0$

    对于求 $LCA$ ,先 $access (y)$ ,再在 $access (x)$ 的时候得到的最后一个跳虚边的点即是它们的 $LCA$

    代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 
      6 using namespace std;
      7 
      8 const int MAXN = 3e05 + 10;
      9 
     10 struct QuerySt {
     11     int pos, time;
     12     int x, y;
     13 
     14     QuerySt () {}
     15     QuerySt (int fpos, int ftime, int fx, int fy) :
     16         pos (fpos), time (ftime), x (fx), y (fy) {}
     17 
     18     bool operator < (const QuerySt& p) const {
     19         return pos == p.pos ? time < p.time : pos < p.pos;
     20     }
     21 } ;
     22 QuerySt Query[MAXN];
     23 int que = 0;
     24 
     25 int N, M;
     26 
     27 int father[MAXN]= {0};
     28 int son[MAXN][2]= {0};
     29 int Sum[MAXN]= {0}, value[MAXN]= {0};
     30 
     31 int isroot (int p) {
     32     return son[father[p]][0] != p && son[father[p]][1] != p;
     33 }
     34 int sonbel (int p) {
     35     return son[father[p]][1] == p;
     36 }
     37 void pushup (int p) {
     38     Sum[p] = Sum[son[p][0]] + Sum[son[p][1]] + value[p];
     39 }
     40 void rotate (int p) {
     41     int fa = father[p], anc = father[fa];
     42     int s = sonbel (p);
     43     son[fa][s] = son[p][s ^ 1];
     44     if (son[fa][s])
     45         father[son[fa][s]] = fa;
     46     if (! isroot (fa))
     47         son[anc][sonbel (fa)] = p;
     48     father[p] = anc;
     49     son[p][s ^ 1] = fa, father[fa] = p;
     50     pushup (fa), pushup (p);
     51 }
     52 void splay (int p) {
     53     for (int fa = father[p]; ! isroot (p); rotate (p), fa = father[p])
     54         if (! isroot (fa))
     55             sonbel (p) == sonbel (fa) ? rotate (fa) : rotate (p);
     56 }
     57 int Access (int p) {
     58     int tp = 0;
     59     for ( ; p; tp = p, p = father[p])
     60         splay (p), son[p][1] = tp, pushup (p);
     61     return tp;
     62 }
     63 void link (int x, int y) { // 注意此时没有makeroot所以需要注意是将y连到x下
     64     splay (y);
     65     father[y] = x;
     66 }
     67 void cut (int x) {
     68     Access (x), splay (x);
     69     father[son[x][0]] = 0, son[x][0] = 0;
     70     pushup (x);
     71 }
     72 
     73 int totq = 0;
     74 int ans[MAXN]= {0};
     75 void Solve () {
     76     sort (Query + 1, Query + que + 1);
     77     for (int i = 1; i <= que; i ++) {
     78         int time = Query[i].time;
     79         int x = Query[i].x, y = Query[i].y;
     80         if (time > 0) {
     81             Access (x), splay (x), ans[time] += Sum[x];
     82             int lca = Access (y);
     83             splay (y), ans[time] += Sum[y];
     84             Access (lca), splay (lca), ans[time] -= (Sum[lca] << 1);
     85         }
     86         else
     87             cut (x), link (y, x);
     88     }
     89 }
     90 
     91 int getnum () {
     92     int num = 0;
     93     char ch = getchar ();
     94 
     95     while (! isdigit (ch))
     96         ch = getchar ();
     97     while (isdigit (ch))
     98         num = (num << 3) + (num << 1) + ch - '0', ch = getchar ();
     99 
    100     return num;
    101 }
    102 
    103 int ind[MAXN]= {0};
    104 int liml[MAXN], limr[MAXN];
    105 int nodes = 1;
    106 int main () {
    107     N = getnum (), M = getnum ();
    108     int lastr = 1, real = 1;
    109     ind[1] = Sum[1] = value[1] = 1, liml[1] = 1, limr[1] = N;
    110     link (1, nodes = lastr = 2);
    111     for (int i = 1; i <= M; i ++) {
    112         int opt = getnum ();
    113         if (opt == 0) {
    114             int l = getnum (), r = getnum ();
    115             link (lastr, ind[++ real] = ++ nodes);
    116             value[nodes] = Sum[nodes] = 1;
    117             liml[real] = l, limr[real] = r;
    118         }
    119         else if (opt == 1) {
    120             int l = getnum (), r = getnum (), x = getnum ();
    121             l = max (l, liml[x]), r = min (r, limr[x]);
    122             if (l > r)
    123                 continue;
    124             link (lastr, ++ nodes);
    125             Query[++ que] = QuerySt (l, i - M, nodes, ind[x]); // 由nodes离开link向index[x]
    126             Query[++ que] = QuerySt (r + 1, i - M, nodes, lastr);
    127             lastr = nodes;
    128         }
    129         else if (opt == 2) {
    130             int x = getnum (), u = getnum (), v = getnum ();
    131             Query[++ que] = QuerySt (x, ++ totq, ind[u], ind[v]); // 由index[u]到index[v]的距离
    132         }
    133     }
    134     Solve ();
    135     for (int i = 1; i <= totq; i ++)
    136         printf ("%d
    ", ans[i]);
    137 
    138     return 0;
    139 }
    140 
    141 /*
    142 5 5
    143 0 1 5
    144 1 2 4 2
    145 0 1 4
    146 2 1 1 3
    147 2 2 1 3
    148 */
  • 相关阅读:
    MySQL MHA高可用方案
    微服务架构的基础框架选择:Spring Cloud还是Dubbo?
    elasticsearch
    spring Cloud构建微服务架构
    SpringBoot-Learning
    JetBrains激活
    正则表达式(java)规则大全
    Android调用Webservice
    UCML针对数据表的修改自定义维护数据变更记录
    SQL游标模板
  • 原文地址:https://www.cnblogs.com/Colythme/p/10179977.html
Copyright © 2011-2022 走看看