BZOJ 1180 CROATIAN 2009 OTOCI/2843 极地旅行社 LCT

题目大意:给出一些初始相互分离的岛,有三个操作,1.分析两点是否联通,如果不连通,在之间连一条边。2.更改一个点的权值。3.询问两点之间路径上所有点的点权和。

思路:基本算是LCT的模板题了吧,好久没写了,基本都要忘了,这是照别人代码写的。。。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 30010
using namespace std;

struct SplayTree{
    SplayTree *son[2],*father;
    int val,sum;
    bool reverse;

    SplayTree(int _);
    bool Check() {
        return father->son[1] == this;
    }
    void Reverse() {
        reverse ^= 1;
        swap(son[0],son[1]);
    }
    void PushUp();
    void PushDown();
}none(0),*nil = &none,*tree[MAX];
SplayTree:: SplayTree(int _) {
    val = sum = _;
    reverse = false;
    son[0] = son[1] = father = nil;
}
void SplayTree:: PushDown() {
    if(father->son[0] == this || father->son[1] == this)
        father->PushDown();
    if(reverse) {
        son[0]->Reverse();
        son[1]->Reverse();
        reverse = false;
    }
}
void SplayTree:: PushUp() {
    sum = son[0]->sum + son[1]->sum + val;
}

int points,asks;

char s[20];

inline void Rotate(SplayTree *a,bool dir)
{
    SplayTree *f = a->father;
    f->son[!dir] = a->son[dir];
    f->son[!dir]->father = f;
    a->son[dir] = f;
    a->father = f->father;
    if(f->father->son[0] == f || f->father->son[1] == f)
        f->father->son[f->Check()] = a;
    f->father = a;
    f->PushUp();
}

inline void Splay(SplayTree *a)
{
    a->PushDown();
    while(a->father->son[0] == a || a->father->son[1] == a) {
        SplayTree *f = a->father;
        if(f->father->son[0] != f && f->father->son[1] != f)
            Rotate(a,!a->Check());
        else if(!f->Check()) {
            if(!a->Check())
                Rotate(f,true),Rotate(a,true);
            else    Rotate(a,false),Rotate(a,true);
        }
        else {
            if(a->Check())
                Rotate(f,false),Rotate(a,false);
            else    Rotate(a,true),Rotate(a,false);
        }
    }
    a->PushUp();
}

inline void Access(SplayTree *a)
{
    SplayTree *temp = nil;
    while(a != nil) {
        Splay(a);
        a->son[1] = temp;
        a->PushUp();
        temp = a;
        a = a->father;
    }
}

inline SplayTree *Find(SplayTree *a)
{
    while(a->father != nil)
        a = a->father;
    return a;
}

inline void ToRoot(SplayTree *a)
{
    Access(a);
    Splay(a);
    a->Reverse();
}

inline void Link(SplayTree *x,SplayTree *y)
{
    ToRoot(x);
    x->father = y;
}

int main()
{
    cin >> points;
    for(int x,i = 1; i <= points; ++i) {
        scanf("%d",&x);
        tree[i] = new SplayTree(x);
    }
    cin >> asks;
    for(int x,y,i = 1; i <= asks; ++i) {
        scanf("%s%d%d",s,&x,&y);
        if(s[0] == 'b') {
            SplayTree *fx = Find(tree[x]);
            SplayTree *fy = Find(tree[y]);
            if(fx == fy)
                puts("no");
            else {
                puts("yes");
                Link(tree[x],tree[y]);
            }
        }
        else if(s[0] == 'p') {
            Splay(tree[x]);
            tree[x]->val = y;
            tree[x]->PushUp();
        }
        else {
            SplayTree *fx = Find(tree[x]);
            SplayTree *fy = Find(tree[y]);
            if(fx != fy)
                puts("impossible");
            else {
                ToRoot(tree[x]);
                Access(tree[y]);
                Splay(tree[y]);
                printf("%d\n",tree[y]->sum);
            }
        }
    }
    return 0;
}

时间: 2024-08-25 12:16:37

BZOJ 1180 CROATIAN 2009 OTOCI/2843 极地旅行社 LCT的相关文章

BZOJ 2843: 极地旅行社( LCT )

LCT.. ------------------------------------------------------------------------ #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #define rep( i , n ) for( int i = 0 ; i < n ; ++i ) #define clr( x , c ) me

BZOJ 2843: 极地旅行社 lct splay

http://www.lydsy.com/JudgeOnline/problem.php?id=2843 https://blog.csdn.net/clove_unique/article/details/50992341 和之前那道题lct求两点距离用lca不同,这道题因为给的边的两个端点是没有顺序的(没法直接按照给的点直接将某个点连到树上),所以bridge需要区间翻转的操作,因为splay维护的是链,所以区间翻转相当于将叶子变成了根,根变成叶子(链翻转过来),然后再把此时的根(x)连到y

【bzoj2843】极地旅行社 LCT

题目描述 不久之前,Mirko建立了一个旅行社,名叫“极地之梦”.这家旅行社在北极附近购买了N座冰岛,并且提供观光服务.当地最受欢迎的当然是帝企鹅了,这些小家伙经常成群结队的游走在各个冰岛之间.Mirko的旅行社遭受一次重大打击,以至于观光游轮已经不划算了.旅行社将在冰岛之间建造大桥,并用观光巴士来运载游客.Mirko希望开发一个电脑程序来管理这些大桥的建造过程,以免有不可预料的错误发生.这些冰岛从1到N标号.一开始时这些岛屿没有大桥连接,并且所有岛上的帝企鹅数量都是知道的.每座岛上的企鹅数量虽

BZOJ2843: 极地旅行社

2843: 极地旅行社 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 90  Solved: 56[Submit][Status] Description 不久之前,Mirko建立了一个旅行社,名叫“极地之梦”.这家旅行社在北极附近购买了N座冰岛,并且提供观光服务.当地最受欢迎的当然是帝企鹅了,这些小家伙经常成群结队的游走在各个冰岛之间. Mirko的旅行社遭受一次重大打击,以至于观光游轮已经不划算了.旅行社将在冰岛之间建造大桥,并用观光巴士来运

【BZOJ2843】极地旅行社(Link-Cut Tree)

[BZOJ2843]极地旅行社(Link-Cut Tree) 题面 BZOJ 题解 \(LCT\)模板题呀 没什么好说的了.. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #includ

【BZOJ2843】极地旅行社 离线+树链剖分+树状数组

[BZOJ2843]极地旅行社 Description 不久之前,Mirko建立了一个旅行社,名叫“极地之梦”.这家旅行社在北极附近购买了N座冰岛,并且提供观光服务.当地最受欢迎的当然是帝企鹅了,这些小家伙经常成群结队的游走在各个冰岛之间.Mirko的旅行社遭受一次重大打击,以至于观光游轮已经不划算了.旅行社将在冰岛之间建造大桥,并用观光巴士来运载游客.Mirko希望开发一个电脑程序来管理这些大桥的建造过程,以免有不可预料的错误发生.这些冰岛从1到N标号.一开始时这些 岛屿没有大桥连接,并且所有

[BZOJ 1879][SDOI 2009]Bill的挑战 题解(状压DP)

[BZOJ 1879][SDOI 2009]Bill的挑战 Description Solution 1.考虑状压的方式. 方案1:如果我们把每一个字符串压起来,用一个布尔数组表示与每一个字母的匹配关系,那么空间为26^50,爆内存: 方案2:把每一个串压起来,多开一维记录匹配字符,那么空间为nlen26,合法,但不便于状态的设计和转移: 方案3:把每一个串同一个位置的字符放在一起,用一个布尔数组记录与每一个小写字母的匹配关系,那么空间为26^15*len,爆内存: 方案4:把每一个串同一个位置

【BZOJ 2843】极地旅行社

复习一下LinkCutTree的模板. #include<cstdio> #include<cstring> #include<algorithm> #define N 30003 #define read(x) x=getint() using namespace std; struct node *null; struct node { node *ch[2], *fa; int d, sum; short rev; bool pl() {return fa->

BZOJ 1180: [CROATIAN2009]OTOCI [LCT]

1180: [CROATIAN2009]OTOCI Time Limit: 50 Sec  Memory Limit: 162 MBSubmit: 961  Solved: 594[Submit][Status][Discuss] Description 给出n个结点以及每个点初始时对应的权值wi.起始时点与点之间没有连边.有3类操作: 1.bridge A B:询问结点A与结点B是否连通.如果是则输出“no”.否则输出“yes”,并且在结点A和结点B之间连一条无向边. 2.penguins A