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 }
  • 相关阅读:
    PHP中防止SQL注入的方法
    SQLmap超详细文档和实例演示
    Spring Cloud 个人心得 理论
    Spring注解说明
    git各角色权限描述
    jenkins调用tomcat重启命令 && tomcat重启脚本
    nginx1.5 升级到1.14
    发布项目
    spring boot 多线程
    Jmeter测试http请求
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8135741.html
Copyright © 2011-2022 走看看