【BZOJ3282】【luoguP3690】【模板】Link Cut Tree (动态树)

problem

题目背景

动态树

题目描述

给定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。

输入输出格式

输入格式:
第1行两个整数,分别为n和m,代表点数和操作数。

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

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

输出格式:
对于每一个0号操作,你须输出x到y的路径上点权的xor和。

输入输出样例

输入样例#1: 复制
3 3
1
2
3
1 1 2
0 1 2
0 1 1
输出样例#1: 复制
3
1
说明

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


analysis

  • 还是LCT板子题差不多是板子在手天下我有

  • 注意两点就好

  • link,cut l i n k , c u t 的两个点不一定联通,用 judge j u d g e 特判一下

  • 还有就是异或和的话 a[i].sum=(a[i].val)xor(a[t[i][0]].sum)xor(a[t[i][1]].sum) a [ i ] . s u m = ( a [ i ] . v a l ) x o r ( a [ t [ i ] [ 0 ] ] . s u m ) x o r ( a [ t [ i ] [ 1 ] ] . s u m )

  • 如此简单


code

#include<bits/stdc++.h>
#define MAXN 300001

using namespace std;

int t[MAXN][2];
int b[MAXN],fa[MAXN],pf[MAXN],st[MAXN];
char s[10];
int n,m;

struct node 
{
    int val,sum,mx,size;
    bool rev;
}a[MAXN];

int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0' || '9'<ch)
    {
        if (ch=='-')f=-1;
        ch=getchar();   
    }
    while ('0'<=ch && ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

void reverse(int x) 
{
    if(x)
    {
        a[x].rev^=1;
        swap(t[x][0],t[x][1]);
    }
}

void down(int x) 
{
    if (a[x].rev) 
    {
        reverse(t[x][0]),reverse(t[x][1]);
        a[x].rev=0;
    }
}

void update(int x) 
{
    if (x)
    {
        a[x].size=a[t[x][0]].size+a[t[x][1]].size+1;
        a[x].sum=a[x].val^a[t[x][0]].sum^a[t[x][1]].sum;
    } 
}

void downdata(int x) 
{
    st[0]=0;
    while (x)st[++st[0]]=x,x=fa[x];
    while (st[0])down(st[st[0]--]);
}

int lr(int x)
{
    return t[fa[x]][1]==x;
}

void rotate(int x) 
{
    int y=fa[x],k=lr(x);
    t[y][k]=t[x][!k];

    if (t[x][!k])fa[t[x][!k]]=y;
    fa[x]=fa[y];

    if (fa[y])t[fa[y]][lr(y)]=x;    
    t[x][!k]=y;

    fa[y]=x,pf[x]=pf[y];
    update(y),update(x);
}

void splay(int x, int y) 
{
    downdata(x);
    while (fa[x]!=y)
    {
        if (fa[fa[x]]!=y)
        {
            if (lr(x)==lr(fa[x]))rotate(fa[x]); 
            else rotate(x);
        } 
        rotate(x);
    }
}

void access(int x) 
{
    for (int y=0;x;update(x),y=x,x=pf[x])
    {
        splay(x,0);
        fa[t[x][1]]=0;
        pf[t[x][1]]=x;
        t[x][1]=y;
        fa[y]=x;
        pf[y]=0;
    }
}

void makeroot(int x) 
{
    access(x); 
    splay(x,0); 
    reverse(x);
}

int getroot(int x)
{
    while (fa[x])x=fa[x];
    return x;
}

bool judge(int x,int y)
{
    makeroot(x);
    access(y);
    splay(x,0);
    return getroot(y)==x;
}

void link(int x,int y) 
{
    if (!judge(x,y))
    {
        makeroot(x); 
        pf[x]=y;
    }
}

void cut(int x,int y) 
{
    if (judge(x,y))
    {
        makeroot(x); 
        access(y);
        splay(x,0);
        t[x][1]=fa[y]=pf[y]=0;
        update(x);
    }
}

int main()
{
    //freopen("readin.txt","r",stdin);
    n=read(),m=read();
    a[0].val=a[0].sum=0;
    for (int i=1;i<=n;i++)
    {
        splay(i,0);
        a[i].val=read();
        update(i);
    }
    while (m--)
    {
        int z=read(),x=read(),y=read();
        if (z==0)
        {
            makeroot(y);
            access(x);
            splay(x,0);
            printf("%d\n",a[x].sum);
        }
        else if (z==1)link(x,y);
        else if (z==2)cut(x,y);
        else 
        {
            splay(x,0);
            a[x].val=y;
            update(x);
        }
    }
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页