bzoj2843极地旅行社题解

  • 题目大意

    有n座小岛,当中每一个岛都有若干帝企鹅。

    一開始岛与岛之间互不相连。有m个操作。各自是在两个岛之间修一座双向桥,若两岛已连通则不修并输出no,若不连通就输出yes并修建。改动一个岛上帝企鹅的数量;询问从岛A到岛B可看到多少帝企鹅,若到不了输出impossible。

  • 题解

    继续试水LCT。LCT维护每一个点自身的企鹅数以及其在Splay下的子树的企鹅数的总和。

    修桥操作要在LCT中询问是否有同样的根,没有则添边。改动时把要被改动的点弄到树根去,直接改动就可以。查询时要先推断是否为同一结点,再推断是否连通。若连通,则把当中一个点x弄到根上,还有一个点y用access连上去,再用Splay把y弄到辅助树的根上。

    这时x一定是y最左端的子孙(由于它是根。中序序列里最靠前)。直接输出y左子树企鹅的总和加上y自己的企鹅数就可以。

  • Code
#include <cstdio>
#include <algorithm>
#include <cstring>
#define maxn 30005
using namespace std;
int n, m;
struct node *nil, *T[maxn], *S[maxn];
struct node
{
    bool rev;
    int val, s;
    node *fa, *lc, *rc;
    node(bool rev = false, int val = 0, int s = 0, node *fa = nil, node *lc = nil, node *rc = nil)
        : rev(rev), val(val), s(s), fa(fa), lc(lc), rc(rc) {}
    inline void update()
    {
        s = lc -> s + rc -> s + val;
    }
    inline void rever()
    {
        rev ^= 1;
        swap(lc, rc);
    }
    inline void pushdown()
    {
        if(rev)
        {
            rev = false;
            lc -> rever(); rc -> rever();
        }
    }
};
inline void zig(node *x)
{
    node *y = x -> fa;
    y -> lc = x -> rc;
    x -> rc -> fa = y;
    x -> rc = y;
    x -> fa = y -> fa;
    if(y == y -> fa -> lc) y -> fa -> lc = x;
    else if(y == y -> fa -> rc) y -> fa -> rc = x;
    y -> fa = x;
    y -> update();
}
inline void zag(node *x)
{
    node *y = x -> fa;
    y -> rc = x -> lc;
    x -> lc -> fa = y;
    x -> lc = y;
    x -> fa = y -> fa;
    if(y == y -> fa -> lc) y -> fa -> lc = x;
    else if(y == y -> fa -> rc) y -> fa -> rc = x;
    y -> fa = x;
    y -> update();
}
void splay(node *x)
{
    int top = 0;
    S[top++] = x;
    for(node *i = x; i == i -> fa -> lc || i == i -> fa -> rc; i = i -> fa)
    {
        S[top++] = i -> fa;
    }
    while(top--) S[top] -> pushdown();
    node *y = nil, *z = nil;
    while(x == x -> fa -> lc || x == x -> fa -> rc)
    {
        y = x -> fa; z = y -> fa;
        if(x == y -> lc)
        {
            if(y == z -> lc) zig(y);
            zig(x);
        }
        else
        {
            if(y == z -> rc) zag(y);
            zag(x);
        }
    }
    x -> update();
}
inline void access(node *x)
{
    for(node *y = nil; x != nil; y = x, x = x -> fa)
    {
        splay(x);
        x -> rc = y;
        x -> update();
    }
}
inline void makeroot(node *x)
{
    access(x); splay(x); x -> rever();
}
inline void lnk(node *x, node *y)
{
    makeroot(x);
    x -> fa = y;
    splay(y);
}
inline node* find(node *x)
{
    access(x); splay(x);
    while(x -> lc != nil) x = x -> lc;
    return x;
}
inline void change(node *x, int k)
{
    makeroot(x);
    x -> val = k;
    x -> update();
}
inline int query(node *x, node *y)
{
    if(x == y) return x -> val;
    if(find(x) != find(y)) return -1;
    makeroot(x);
    access(y);
    splay(y);
    return (y -> lc -> s + y -> val);
}
int main()
{
    int a, b, c;
    char ch[10];
    scanf("%d", &n);
    nil = new node(); *nil = node();
    for(int i = 1; i <= n; ++i) T[i] = new node();
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &(T[i] -> val));
        T[i] -> update();
    }
    scanf("%d", &m);
    while(m--)
    {
        scanf("%s%d%d", ch, &a, &b);
        if(ch[0] == ‘b‘)
        {
            if(find(T[a]) != find(T[b]))
            {
                lnk(T[a], T[b]); puts("yes");
            }
            else puts("no");
        }
        else if(ch[0] == ‘p‘)
        {
            change(T[a], b);
        }
        else
        {
            c = query(T[a], T[b]);
            if(c == -1) puts("impossible");
            else printf("%d\n", c);
        }
    }
    for(int i = 1; i <= n; ++i)
    {
        delete T[i];
        T[i] = NULL;
    }
    delete nil;
    nil = NULL;
    return 0;
}
时间: 2024-08-30 01:14:50

bzoj2843极地旅行社题解的相关文章

BZOJ2843: 极地旅行社

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

bzoj2843极地旅行社

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

bzoj2843: 极地旅行社 离线+树链剖分

离线建树,树链剖分. #include<bits/stdc++.h> #define N 100010 #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define L l,M,P #define R M+1,r,S #define Z int l=1,int r=n,int k=1 using namespace std; int n,m; struct edge{ edge* s; int

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

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

【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

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

【bzoj2843】极地旅行社 LCT

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

【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 CROATIAN 2009 OTOCI/2843 极地旅行社 LCT

题目大意:给出一些初始相互分离的岛,有三个操作,1.分析两点是否联通,如果不连通,在之间连一条边.2.更改一个点的权值.3.询问两点之间路径上所有点的点权和. 思路:基本算是LCT的模板题了吧,好久没写了,基本都要忘了,这是照别人代码写的... CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 30010 using