共价大爷游长沙 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
原文地址:https://www.cnblogs.com/MingSD/p/9641352.html