zoukankan      html  css  js  c++  java
  • 共价大爷游长沙 lct 维护子树信息

    这个题目的关键就是判断 大爷所有可能会走的路 会不会经过询问的边。

    某一条路径经过其中的一条边, 那么2个端点是在这条边的2测的。

    现在我们要判断所有的路径是不是都经过 u -> v 我们以u为根节点, 如果所有的路劲的起点 有且仅有一个点在 v 的子树内 我们就可以知道这个边是合法的。

    那么我们每次增加路劲之后, 都在2个端点都亦或上某一个值, 每次判断的时候都判断这个v的子树内整颗树的亦或和是不是等于整体亦或和。如果是 那就说明合法。

    现在我们用lct维护这个树。

    在这个地方我们需要用lct维护子树信息。

    普通的lct是维护一条链的。

    lct维护子树的话, 我们需要新开一个状态 存下所有的 非偏爱子节点的 的值。

    每次切换偏爱子节点的时候, 假设  u 的偏爱子节点为 v 现在转变成x。

    那我们就需要把 x的值从非偏爱中取出, 然后在把u的值放入。

    这样我们就维护好了这个东西。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define lch(x) tr[x].son[0]
     12 #define rch(x) tr[x].son[1]
     13 #define max3(a,b,c) max(a,max(b,c))
     14 #define min3(a,b,c) min(a,min(b,c))
     15 typedef pair<int,int> pll;
     16 const int inf = 0x3f3f3f3f;
     17 const LL INF = 0x3f3f3f3f3f3f3f3f;
     18 const LL mod =  (int)1e9+7;
     19 const int N = 5e5 + 100;
     20 struct Node{
     21     int rev, rt;
     22     int son[2], pre;
     23     int sum, vsum, key;
     24     void init(){
     25         rt = 1; rev = pre = son[0] = son[1] = 0;
     26         sum = vsum = key = 0;
     27     }
     28 }tr[N];
     29 void Push_Rev(int x){
     30     if(!x) return ;
     31     swap(lch(x), rch(x));
     32     tr[x].rev ^= 1;
     33 }
     34 void Push_Up(int x){
     35     if(!x) return ;
     36     tr[x].sum = tr[x].key ^ tr[lch(x)].sum ^ tr[rch(x)].sum ^ tr[x].vsum;
     37 }
     38 void Push_Down(int x){
     39    if(tr[x].rev){
     40         tr[x].rev = 0;
     41         Push_Rev(lch(x));
     42         Push_Rev(rch(x));
     43     }
     44 }
     45 void Rev(int x){
     46     if(!tr[x].rt) Rev(tr[x].pre);
     47     Push_Down(x);
     48 }
     49 void rotate(int x){
     50     if(tr[x].rt) return;
     51     int y = tr[x].pre, z = tr[y].pre;
     52     int k = (rch(y) == x);
     53     tr[y].son[k] = tr[x].son[k^1];
     54     tr[tr[y].son[k]].pre = y;
     55     tr[x].son[k^1] = y;
     56     tr[y].pre = x;
     57     tr[x].pre = z;
     58     if(tr[y].rt) tr[y].rt = 0, tr[x].rt = 1;
     59     else tr[z].son[rch(z) == y] = x;
     60     Push_Up(y);
     61 }
     62 void Splay(int x){
     63      Rev(x);
     64      while(!tr[x].rt){
     65         int y = tr[x].pre, z = tr[y].pre;
     66         if(!tr[y].rt){
     67             if(( x == rch(y) ) != (y == rch(z))) rotate(y);
     68             else rotate(x);
     69         }
     70         rotate(x);
     71     }
     72     Push_Up(x);
     73 }
     74 void Access(int x){
     75     int y = 0;
     76     do{
     77         Splay(x);
     78         tr[rch(x)].rt = 1;
     79         tr[x].vsum ^= tr[rch(x)].sum;
     80         rch(x) = y;
     81         tr[x].vsum ^= tr[rch(x)].sum;
     82         tr[y].rt = 0;
     83         Push_Up(x);
     84         y = x;
     85         x = tr[x].pre;
     86     }while(x);
     87 }
     88 void Make_rt(int x){
     89     Access(x);
     90     Splay(x);
     91     Push_Rev(x);
     92 }
     93 void link(int u, int v){
     94     Make_rt(u);
     95     Access(v);
     96     Splay(v);
     97     tr[u].pre = v;
     98     tr[v].
     99     vsum ^= tr[u].sum;
    100     Push_Up(v);
    101 }
    102 void cut(int u, int v){
    103     Make_rt(u);
    104     Access(v);
    105     Splay(v);
    106     tr[lch(v)].pre = 0;
    107     tr[lch(v)].rt = 1;
    108     tr[v].pre = 0;
    109     lch(v) = 0;
    110     Push_Up(v);
    111 }
    112 int a[N], b[N], c[N];
    113 int main(){
    114     int n, m;
    115     scanf("%d%d%d", &n, &n, &m);
    116     int x, y;
    117     for(int i = 1; i <= n; i++)
    118         tr[i].init();
    119     for(int i = 1; i < n; i++){
    120         scanf("%d%d", &x, &y);
    121         link(x, y);
    122     }
    123     int op, u, v, tot = 0;
    124     int jud = 0;
    125     for(int i = 1; i <= m; i++){
    126         scanf("%d", &op);
    127         if(op == 1){
    128             scanf("%d%d%d%d", &x, &y, &u, &v);
    129             cut(x, y);
    130             link(u, v);
    131         }
    132         if(op == 2){
    133             ++tot;
    134             scanf("%d%d", &a[tot], &b[tot]);
    135             x = a[tot], y = b[tot];
    136             c[tot] = rand()>>15|rand();
    137             Make_rt(x);
    138             tr[x].sum ^= c[tot];
    139             tr[x].key ^= c[tot];
    140             Make_rt(y);
    141             tr[y].sum ^= c[tot];
    142             tr[y].key ^= c[tot];
    143             jud ^= c[tot];
    144         }
    145         if(op == 3){
    146             scanf("%d", &v);
    147             x = a[v], y = b[v], u = c[v];
    148             Make_rt(x);
    149             tr[x].sum ^= u;
    150             tr[x].key ^= u;
    151             Make_rt(y);
    152             tr[y].sum ^= u;
    153             tr[y].key ^= u;
    154             jud ^= u;
    155         }
    156         if(op == 4){
    157             scanf("%d%d", &x, &y);
    158             Make_rt(x);
    159             Access(y);
    160             Splay(x);
    161             if(jud == tr[y].sum) puts("YES");
    162             else puts("NO");
    163         }
    164     }
    165     return 0;
    166 }
    View Code
  • 相关阅读:
    Linux 配置gitee
    Linux C errno出错处理
    Linux C进程时间:墙上时钟时间,用户CPU时间,系统CPU时钟时间
    编译错误: 对‘aio_read’未定义的引用
    Linux 异步IO(AIO)
    Linux getaddrinfo获得本机ip地址为何127.0.1.1?
    Linux 文件截断的几种方式
    如何创建守护进程?
    守护进程, 协同进程, 僵尸进程, 孤儿进程概念理解
    对线程安全, 可重入函数, 异步安全的理解
  • 原文地址:https://www.cnblogs.com/MingSD/p/9641352.html
Copyright © 2011-2022 走看看