HDU - 4010 link/cut tree

这是一篇关于HDU 4010题目的博客,讲述了如何处理link/cut tree的问题。博主在解决过程中遇到了理解错误,误将操作2解读为断开x与y的边,实际上该操作是将x设为根并断开y与其父节点的连接。博主在修正理解后成功AC,但指出自己对于Link/Cut Tree的掌握还不够熟练。
摘要由CSDN通过智能技术生成

HDU - 4010

题目链接

题意

给一棵树,四个操作
1 x y x~y连一条边
2 x y 把x变成根,断开y跟他的父节点
3 w x y 把 x 到 y 路径上的点权加w
4 x y 查询 x ~ y 路径上的点权的最大值

我的zz问题

做这个题真的是脑抽
题要看对,2操作不是断开x跟y的边。题看错wa死了
2操作

void cut(int x,int y)
{
    makeroot(x);
    if(findroot(y) != x || node[y].fa != x || node[y].ch[0])
        return;
    node[y].fa =0 ;
    node[x].ch[1] = 0;
    update(x);
}
int solve(int x,int y)
{
    makeroot(x);
    if(findroot(y) != x)
        return 1;
    splaying(y);
    int p = node[y].ch[0];
    // while(node[p].ch[1])
    //     p = node[p].ch[1];
    // cut(p,y);
    node[p].fa =0 ;
    node[y].ch[0] = 0;
    return 0;
}

可能是我lct不够熟练(这才是做的第二道题)
上面代码注释掉的wa,改成下面的就ac。
原因:没有down( p ) … … . . . … . . … . … 菜到了极点。
应该是

int solve(int x,int y)
{
    makeroot(x);
    if(findroot(y) != x)
        return 1;
    splaying(y);
    int p = node[y].ch[0];
    while(node[p].ch[1])
    {
        down(p);
        p = node[p].ch[1];
    }
    cut(p,y);
    // node[p].fa =0 ;
    // node[y].ch[0] = 0;
    return 0;
}

就可以ac 。
烦烦烦烦烦烦

#include<algorithm>
#include<iostream>
#include <cstdio>
#include <string>
#include <queue>
#include <cstring>
#include <stack>
#include <map>
#include <bitset>
#include <set>
#include <unordered_set>
#include <climits>
#include <cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<double,double> pdd;
typedef unsigned long long ull;
typedef unordered_set<int>::iterator sit;
#define st first
#define sd second
#define mkp make_pair
#define pb push_back
void tempwj(){freopen("hash.in","r",stdin);freopen("hash.out","w",stdout);}
ll gcd(ll a,ll b){return b == 0 ? a : gcd(b,a % b);}
ll qpow(ll a,ll b,ll mod){a %= mod;ll ans = 1;while(b > 0){if(b & 1)ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;}
struct cmp{bool operator()(const pii & a, const pii & b){return a.second > b.second;}};
int lb(int x){return  x & -x;}
//friend bool operator < (Node a,Node b)   重载
const int inf = INT_MAX;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9+7;
const int maxn = 6e5+10;
const int M = 1e6 + 2;



struct Node
{
    int ch[2],val,maxx,siz,fa,rev,tag;
}node[maxn];
bool ntroot(int no)
{
    return node[node[no].fa].ch[0] == no || node[node[no].fa].ch[1] == no;
}
void xiugai(int no)
{
    swap(node[no].ch[0],node[no].ch[1]);
    node[no].rev ^= 1;
}
void xiugai2(int no,int val)
{
    node[no].val += val;
    node[no].tag += val;
    node[no].maxx += val;
}
void down(int no)
{
    if(node[no].rev)
    {
        if(node[no].ch[0])
            xiugai(node[no].ch[0]);
        if(node[no].ch[1])
            xiugai(node[no].ch[1]);
        node[no].rev = 0;
    }
    if(node[no].tag)
    {
        if(node[no].ch[0])
            xiugai2(node[no].ch[0],node[no].tag);
        if(node[no].ch[1])
            xiugai2(node[no].ch[1],node[no].tag);
        node[no].tag = 0;
    }
}
void update(int no)
{
    node[no].siz = node[node[no].ch[0]].siz + node[node[no].ch[1]].siz + 1;
    node[no].maxx = node[no].val;
    if(node[no].ch[0])
        node[no].maxx = max(node[no].maxx,node[node[no].ch[0]].maxx);
    if(node[no].ch[1])
        node[no].maxx = max(node[no].maxx,node[node[no].ch[1]].maxx);
}
int ident(int no,int fa)
{
    return node[fa].ch[1] == no;
}
void connect(int x,int y,int f)
{
    node[x].fa = y;
    node[y].ch[f] = x;
}
void pushall(int no)
{
    if(ntroot(no))
        pushall(node[no].fa);
    down(no);
}
void zxbl(int no)
{
    if(no == 0)
        return;
    zxbl(node[no].ch[0]);
    printf("%d ",node[no].val);
    zxbl(node[no].ch[1]);
}
void debug(int no)
{
    zxbl(no);
    printf("\n");
}
void change(int x)
{
    int f = node[x].fa;
    int ff = node[f].fa;
    int k = ident(x,f);
    connect(node[x].ch[k^1],f,k);
    node[x].fa = ff;
    if(ntroot(f))
        node[ff].ch[ident(f,ff)] = x;
    connect(f,x,k^1);
    update(f);
    update(x);
}
void splaying(int x)
{
    pushall(x);
    while(ntroot(x))
    {
        int f = node[x].fa;
        int ff = node[f].fa;
        if(ntroot(f))
            ident(f,ff)^ident(x,f) ? change(x) : change(f);
        change(x);
    }
}
void access(int x)
{
    for (int y = 0; x; y = x,x = node[x].fa)
    {
        splaying(x);
        node[x].ch[1] = y;
        update(x);
    }
}
void makeroot(int x)
{
    access(x);
    splaying(x);
    xiugai(x);
}
int findroot(int x)
{
    access(x);
    splaying(x);
    while(node[x].ch[0])
    {
        down(x);
        x = node[x].ch[0];
    }
    splaying(x);
    return x;
}
int link(int x,int y)
{
    makeroot(x);
    if(findroot(y) == x)
        return 1;
    node[x].fa = y;
    return 0;
}
void cut(int x,int y)
{
    makeroot(x);
    if(findroot(y) != x || node[y].fa != x || node[y].ch[0])
        return;
    node[y].fa =0 ;
    node[x].ch[1] = 0;
    update(x);
}
void split(int x,int y)
{
    makeroot(x);
    access(y);
    splaying(y);
}
int solve(int x,int y)
{
    makeroot(x);
    if(findroot(y) != x)
        return 1;
    splaying(y);
    int p = node[y].ch[0];
    while(node[p].ch[1])
    {
        down(p);
        p = node[p].ch[1];
    }
    cut(p,y);
    // node[p].fa =0 ;
    // node[y].ch[0] = 0;
    return 0;
}
int opchange(int x,int y,int val)
{
    makeroot(x);
    if(findroot(y) != x)
        return 1;
    split(x,y);
    xiugai2(y,val);
    return 0;
}
int opquery(int x,int y)
{
    makeroot(x);
    if(findroot(y) != x)
        return -1;
    split(x,y);
    return node[y].maxx;
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for (int i = 0; i <= n; i ++ )
        {
            node[i].siz = 1;
            node[i].val = 0;
            node[i].maxx = 0;
            node[i].ch[0] = node[i].ch[1] = node[i].rev = node[i].tag = node[i].fa = 0;
        }
        node[0].siz = 0;
        node[0].maxx = -inf;
        for (int i = 1; i < n;  i ++ )
        {
            int x,y;
            scanf("%d%d",&x,&y);
            link(x,y);
        }
        for (int i = 1; i<= n; i ++ )
        {
            int x;
            scanf("%d",&x);
            node[i].val = x;
            node[i].maxx = x;
        }
        int q;
        scanf("%d",&q);
        while(q -- )
        {
            int f,x,y;
            scanf("%d%d%d",&f,&x,&y);
            if(f == 1)
            {
                if(link(x,y))
                    printf("-1\n");
            }
            else if(f == 2)
            {
                if(x == y || solve(x,y))
                    printf("-1\n");
            }
            else if(f == 3)
            {
                int w;
                scanf("%d",&w);
                if(opchange(y,w,x))
                    printf("-1\n");
            }
            else if(f == 4)
            {
                printf("%d\n",opquery(x,y));
            }
            // for (int i = 1; i <= n; i ++ )
            // {
            //     if(!ntroot(i))
            //         debug(i);
            // }
            // printf("\n\n");
        }
        printf("\n");
    }
        
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值