Luogu P3690 [Template] Link Cut Tree (Dynamic Tree)

topic background

dynamic tree

Topic description

Given n points and a weight for each point, you are required to process the next m operations. There are 4 types of operations. Operations are numbered from 0 to 3. Points are numbered from 1 to n.

0: followed by two integers (x, y) representing the xor sum of the weights of the points on the path from x to y. Ensure that x to y are connected.

1: Followed by two integers (x, y), which represent the connection between x and y. If x and y are already connected, there is no need to connect.

2: Followed by two integers (x, y), representing the deletion of the edge (x, y), and the existence of the edge (x, y) is not guaranteed.

3: Followed by two integers (x, y), which means changing the weight on point x to y.

Input and output format

Input format:

 

Line 1 has two integers, n and m, representing the number of points and operands.

Lines 2 to n+1, each line is an integer, the integer is within [1, 10^9], representing the weight of each point.

Lines n+2 to n+m+1, each line has three integers representing the type of operation and the amount required for the operation.

 

Output format:

 

For each operation 0, you have to output the xor sum of the weights on the path from x to y.

 

Input and output example

Input Example #1:  Copy
3 3
1
2
3
1 1 2
0 1 2
0 1 1
Output Sample #1:  Copy
3
1

illustrate

Data range:  1 \leq N, M \leq 3 \cdot {10}^5 1 N , M 3 1 0 5

 

 

Watched an afternoon lecture

Watched the code overnight

It is almost understood, but there is still a potential hidden danger that has not been solved, which is the metaphysical pushdown function in the code

Let's sort it out when you figure it out.

 

// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=3 * 1e5 + 10;
inline int read()
{
    char c = getchar();int x = 0,f = 1;
    while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();}
    while(c >= '0' && c <= '9'){x = x * 10 + c - '0',c = getchar();}
    return x * f;
}
#define fa(x) T[x].f
#define ls(x) T[x].ch[0]
#define rs(x) T[x].ch[1]
int v[MAXN];
struct node {
    int f, ch[2], s;
    bool r;
}T[MAXN];
int ident( int x) {
     return T[fa(x)].ch[ 0 ] == x ? 0 : 1 ; // determine which son of the father the node is 
}
 int connect( int x, int fa, int how ) {
    T [x] .f = fa;
    T[fa].ch[how] =x; // connect 
}
inline bool IsRoot( int x) { // If it is the root in splay, return 1, otherwise return 0 
    return ls( fa(x) ) != x && rs( fa(x) ) != x;
     // Two used A property
     // 1. If the edge between x and fa(x) is a virtual edge, then its parent's children will not have him (not in the same splay)
     // 2. The root node of the splay and its parent are The edge between is an imaginary edge 
}
 void update( int x) {
    T[x].s = T[ls(x)].s ^ T[rs(x)].s ^ v[x]; // maintain the XOR sum on the path 
}
 void pushdown( int x) {
     if (T[x].r) {
        swap(ls(x),rs(x));
        T [ls (x)]. R ^ = 1 ;
        T[rs(x)].r ^= 1;
        T[x].r = 0 ; // mark download 
    }
}
void rotate( int x) {
     int Y = T[x].f, R = T[Y].f, Yson = ident(x), Rson = ident(Y);
     int B = T[x].ch[ Yson ^ 1 ];
     // Why is Q written like this ************************************** ****** 
    
    T[x].f = R;
     if (! IsRoot(Y))
        connect(x, R, Rson);
    // If you don't judge whether y is the root node, then when y is the root node, the son of node 0 will be updated to x
     // In this way, x can never be judged as the root node, and the loop will go on indefinitely.
     // But if the father of x is not updated here, there will be infinite recursion 
    connect(B, Y, Yson);
    connect(Y, x, Yson ^ 1);
    update(Y); update(x);
}
int st[MAXN];
void splay(int x) {
    int y = x, top = 0;
    st[ ++top] = y;
     while (!IsRoot(y)) st[++top] = y = fa(y);
     while (top) pushdown(st[top-- ]);
     // because of the rotation It will not process tags when splaying, so all tags should be downloaded before splay 
    for ( int y = fa(x); !IsRoot(x); rotate(x), y = fa(x)) // As long as it is not the root , rotate 
        if (! IsRoot(y))
            rotate( ident(x) == ident(y) ? x : y );
}
void access( int x) { // access x node 
    for ( int y = 0 ; x; x = fa(y = x))
        splay(x), rs(x) = y, update(x);
     // First, splay x to the root of the balanced tree where it is located, so as to ensure that its right child is the corresponding heavy chain in the original tree (the depth ratio of the right child It's big)
     // y is the son of x in splay, change the right son of x to y, that is, change the edge between x and y into a real edge
     // change the node order, need to update 
}
 void makeroot( int x) { // Change x to the root node of the original tree 
    access(x);
    splay(x);
    T[x].r ^= 1;
    pushdown(x);
    // First visit x, then turn x to the root,
     // Note that when accessing, it is the right son of the connection, which will destroy the order, so we need to flip the left and right sons 
}
 int findroot( int x) { // Find the root node of x in the original tree 
    access(x);splay(x);
     while (ls(x)) x = ls(x); // find the point with the smallest depth is the root node 
    return x;
}
void split(int x, int y) {
    makeroot(x); // First set x as the root node 
    access(y); splay(y);
     // Then visit y, and then transfer y to the root node, so that y maintains the x - y path xor 
}
 void link( int x, int y) {
    makeroot(x); // set x as the root node 
    if (findroot(y) != x ) fa(x) = y;
     // if x and y are not in the same splay, set y as the father of x 
     // Because the depth of x and y cannot be judged, there is no need to update the son of y here 
}
 void cut( int x, int y) {
    makeroot (x);
    if(findroot(y) == x && fa(x) == y && !rs(x)) { 
        fa (x) = T [y] .ch [ 0 ] = 0 ;
        update(y);
    }
    // Note that after findroot(y), y will become the root node 
     // For the third judgment
     // Such a tree can be constructed 
     // x
     // fuck
     // y
     // in splay this is
     // y
     / / x
     // fuck
     // so obviously x and y are not connected 
}
 int main()
{
    #ifdef WIN32
    freopen("a.in","r",stdin);
    //freopen("a.out","w",stdout);
    #else
    #endif
    int N = read(), M = read();
    for(int i = 1; i <= N; i++) v[i] = read();
    for(int i = 1; i <= M; i++) {
        int opt = read(), x = read(), y = read();
        if(opt == 0) split(x, y), printf("%d\n",T[y].s);
        else if(opt == 1) link(x, y);
        else if(opt == 2) cut(x, y);
        else if(opt == 3) splay(x), v[x] = y;
    }
    return 0;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325044543&siteId=291194637