zoukankan      html  css  js  c++  java
  • [Luogu 3690]【模板】Link Cut Tree (动态树)

    Description

    给定N个点以及每个点的权值,要你处理接下来的M个操作。操作有4种。操作从0到3编号。点从1到N编号。

    0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和。保证x到y是联通的。

    1:后接两个整数(x,y),代表连接x到y,若x到Y已经联通则无需连接。

    2:后接两个整数(x,y),代表删除边(x,y),不保证边(x,y)存在。

    3:后接两个整数(x,y),代表将点X上的权值变成Y。

    Input

    第1行两个整数,分别为N和M,代表点数和操作数。

    第2行到第N+1行,每行一个整数,整数在[1,10^9]内,代表每个点的权值。

    第N+2行到第N+M+1行,每行三个整数,分别代表操作类型和操作所需的量。

    Output

    对于每一个0号操作,你须输出X到Y的路径上点权的Xor和。

    Sample Input

    3 3
    1
    2
    3
    1 1 2
    0 1 2
    0 1 1

    Sample Output

    3
    1

    HINT

    数据范围: $ 1 leq N, M leq 3 cdot {10}^5 $

    题解

    维护$xor$和维护子树大小类似。

    这道题用到的技巧:

    找根:$access(o)$及$splay(o)$后一直往左走。最后一个节点就是根。(理由:由于$LCT$中$splay$的性质:按深度作为键值);

    判断是否之间有边:再$cut$之前,判断根的左儿子是否是另外一个点。(理由:若存在边,则包含这条边的$splay$只有两个节点)。

      1 //It is made by Awson on 2017.12.28
      2 #include <map>
      3 #include <set>
      4 #include <cmath>
      5 #include <ctime>
      6 #include <queue>
      7 #include <stack>
      8 #include <vector>
      9 #include <cstdio>
     10 #include <string>
     11 #include <cstdlib>
     12 #include <cstring>
     13 #include <iostream>
     14 #include <algorithm>
     15 #define LL long long
     16 #define LD long double
     17 #define Max(a, b) ((a) > (b) ? (a) : (b))
     18 #define Min(a, b) ((a) < (b) ? (a) : (b))
     19 using namespace std;
     20 const int N = 3e5;
     21 
     22 struct Link_Cut_Tree {
     23     int ch[N+5][2], pre[N+5], val[N+5], xr[N+5], isrt[N+5], rev[N+5];
     24     void pushup(int o) {
     25     if (!o) return;
     26     xr[o] = xr[ch[o][0]]^xr[ch[o][1]]^val[o];
     27     }
     28     void pushdown(int o) {
     29     if (!o || !rev[o]) return;
     30     int ls = ch[o][0], rs = ch[o][1];
     31     swap(ch[ls][0], ch[ls][1]), swap(ch[rs][0], ch[rs][1]);
     32     rev[ls] ^= 1, rev[rs] ^= 1, rev[o] = 0;
     33     }
     34     void push(int o) {
     35     if (!isrt[o]) push(pre[o]);
     36     pushdown(o);
     37     }
     38     void rotate(int o, int kind) {
     39     int p = pre[o];
     40     ch[p][!kind] = ch[o][kind], pre[ch[o][kind]] = p;
     41     if (isrt[p]) isrt[o] = 1, isrt[p] = 0;
     42     else ch[pre[p]][ch[pre[p]][1] == p] = o;
     43     pre[o] = pre[p];
     44     ch[o][kind] = p, pre[p] = o;
     45     pushup(p), pushup(o);
     46     }
     47     void splay(int o) {
     48     push(o);
     49     while (!isrt[o]) {
     50         if (isrt[pre[o]]) rotate(o, ch[pre[o]][0] == o);
     51         else {
     52         int p = pre[o], kind = ch[pre[p]][0] == p;
     53         if (ch[p][kind] == o) rotate(o, !kind), rotate(o, kind);
     54         else rotate(p, kind), rotate(o, kind);
     55         }
     56     }
     57     }
     58     void access(int o) {
     59     int y = 0;
     60     while (o) {
     61         splay(o);
     62         xr[o] ^= xr[ch[o][1]];
     63         isrt[ch[o][1]] = 1, isrt[ch[o][1] = y] = 0;
     64         pushup(o);
     65         o = pre[y = o];
     66     }
     67     }
     68     void makeroot(int o) {
     69     access(o), splay(o);
     70     rev[o] ^= 1, swap(ch[o][0], ch[o][1]);
     71     }
     72     int find(int o) {
     73     access(o), splay(o);
     74     while (ch[o][0]) o = ch[o][0];
     75     return o;
     76     }
     77     void link(int x, int y) {
     78     int p = find(x), q = find(y);
     79     if (p == q) return;
     80     makeroot(x); pre[x] = y;
     81     }
     82     void cut(int x, int y) {
     83     makeroot(x), access(y), splay(y);
     84     if (ch[y][0] != x) return;
     85     xr[y] ^= xr[x], ch[y][0] = pre[x] = 0, isrt[x] = 1;
     86     }
     87     int query(int x, int y) {
     88     makeroot(x), access(y), splay(y);
     89     return xr[y];
     90     }
     91     void update(int o, int key) {
     92     makeroot(o); val[o] = key; pushup(o);
     93     }
     94 }T;
     95 int n, m, x, opt, y;
     96 
     97 void work() {
     98     scanf("%d%d", &n, &m);
     99     for (int i = 1; i <= n; i++) {
    100     scanf("%d", &x);
    101     T.val[i] = T.xr[i] = x, T.isrt[i] = 1;
    102     }
    103     while (m--) {
    104     scanf("%d%d%d", &opt, &x, &y);
    105     if (opt == 0) printf("%d
    ", T.query(x, y));
    106     else if (opt == 1) T.link(x, y);
    107     else if (opt == 2) T.cut(x, y);
    108     else T.update(x, y);
    109     }
    110 }
    111 int main() {
    112     work();
    113     return 0;
    114 }
  • 相关阅读:
    013.ES6 -对象字面量增强型写法
    012. ES6
    011. ES6 语法
    10. 9. Vue 计算属性的setter和getter 以及 计算属性的缓存讲解
    4. Spring MVC 数据响应方式
    3. SpringMVC 组件解析
    9. Vue 计算属性
    【洛谷 2984】给巧克力
    【洛谷 1821】捉迷藏 Hide and Seek
    【洛谷 1821】银牛派对Silver Cow Party
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8135741.html
Copyright © 2011-2022 走看看