SPOJ - OTOCI LCT

OTOCI

Time Limit: 1 Sec

Memory Limit: 256 MB

题目连接

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18141

Description

Some time ago Mirko founded a new tourist agency named "Dreams of Ice". The agency purchased N icy islands near the South Pole and now offers excursions. Especially popular are the emperor penguins, which can be found in large numbers on the islands.

Mirko‘s agency has become a huge hit; so big that it is no longer cost-effective to use boats for the excursions. The agency will build bridges between islands and transport tourists by buses. Mirko wants to introduce a computer program to manage the bridge building process so that fewer mistakes are made.

The islands are numbered 1 through N. No two islands are initially connected by bridges. The initial number of penguins on each island is known. That number may change, but will always be between 0 and 1000 (inclusive).

Your program must handle the following three types of commands:

  • "bridge A B" – an offer was received to build a bridge between islands A and B (A and B will be different). To limit costs, your program must accept the offer only if there isn‘t already a way to get from one island to the other using previously built bridges. If the offer is accepted, the program should output "yes", after which the bridge is built. If the offer is rejected, the program should output "no".
  • "penguins A X" – the penguins on island A have been recounted and there are now X of them. This is an informative command and your program does not need to respond.
  • "excursion A B" – a group of tourists wants an excursion from island A to island B. If the excursion is possible (it is possible to get from island A to B), the program should output the total number of penguins the tourists would see on the excursion (including islands A and B). Otherwise, your program should output "impossible".

Input

The first line contains the integer N (1 ≤ N ≤ 30 000), the number of islands.

The second line contains N integers between 0 and 1000, the initial number of penguins on each of the islands.

The third line contains an integer Q (1 ≤ Q ≤ 300 000), the number of commands.

Q commands follow, each on its own line.

Output

Output the responses to commands "bridge" and "excursion", each on its own line.

Sample Input

5
4 2 4 5 6
10
excursion 1 1
excursion 1 2
bridge 1 2
excursion 1 2
bridge 3 4
bridge 3 5
excursion 4 5
bridge 1 3
excursion 2 4
excursion 2 5

Sample Output

4
impossible
yes
6
yes
yes
15
yes
15
16

HINT

题意

让你维护一棵树

link操作,update操作,query链上的点权和

题解:

就lct的基本操作啦

这种就主要维护里面的update信息

代码:

//qscqesze
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <bitset>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 1205000
#define mod 1000000007
#define eps 1e-9
#define e exp(1.0)
#define PI acos(-1)
#define lowbit(x) (x)&(-x)
const double EP  = 1E-10 ;
int Num;
//const int inf=0x7fffffff;
const ll inf=999999999;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
//*************************************************************************************
const int MAXN = 100010;
struct Node {
    Node *ch[2], *p; int size, value;
    int w;
    bool rev;
    Node(int t = 0);
    inline bool dir(void) {return p->ch[1] == this;}
    inline void SetC(Node *x, bool d) {
        ch[d] = x; x->p = this;
    }
    inline void Rev(void) {
        swap(ch[0], ch[1]); rev ^= 1;
    }
    inline void Push(void) {
        if (rev) {
            ch[0]->Rev();
            ch[1]->Rev();
            rev = 0;
        }
    }
    inline void Update(void) {
        value = w+ch[0]->value + ch[1]->value;
        size = ch[0]->size + ch[1]->size + 1;
    }
}Tnull, *null = &Tnull, *fim[MAXN];
// 要记得额外更新null的信息
Node::Node(int _value){ch[0] = ch[1] = p = null; rev = 0;w = value = _value;}
inline bool isRoot(Node *x) {return x->p == null || (x != x->p->ch[0] && x != x->p->ch[1]);}
inline void rotate(Node *x) {
    Node *p = x->p; bool d = x->dir();
    p->Push(); x->Push();
    if (!isRoot(p)) p->p->SetC(x, p->dir()); else x->p = p->p;
    p->SetC(x->ch[!d], d);
    x->SetC(p, !d);
    p->Update();
}
inline void splay(Node *x) {
    x->Push();
    while (!isRoot(x)) {
        if (isRoot(x->p)) rotate(x);
        else {
            if (x->dir() == x->p->dir()) {rotate(x->p); rotate(x);}
            else {rotate(x); rotate(x);}
        }
    }
    x->Update();
}
inline Node* Access(Node *x) {
    Node *t = x, *q = null;
    for (; x != null; x = x->p) {
        splay(x); x->ch[1] = q; q = x;
    }
    splay(t); //info will be updated in the splay;
    return q;
}
inline void Evert(Node *x) {
    Access(x); x->Rev();
}
inline void link(Node *x, Node *y) {
    Evert(x); x->p = y;
}
inline Node* getRoot(Node *x) {
    Node *tmp = x;
    Access(x);
    while (tmp->Push(), tmp->ch[0] != null) tmp = tmp->ch[0];
    splay(tmp);
    return tmp;
}
// 一定要确定x和y之间有边
inline void cut(Node *x, Node *y) {
    Access(x); splay(y);
    if (y->p != x) swap(x, y);
    Access(x); splay(y);
    y->p = null;
}
inline Node* getPath(Node *x, Node *y) {
    Evert(x); Access(y);
    return y;
}
inline void clear(void) {
    null->rev = 0; null->size = 0; null->value = 0;
}

int main()
{
    int n=read();
    for(int i=1;i<=n;i++)
    {
        int x = read();
        fim[i] = new Node(x);
    }
    int q = read();
    char s[25];
    while(q--)
    {
        scanf("%s",s);
        if(s[0]==‘e‘)
        {
            int x=read(),y=read();
            if(getRoot(fim[x])!=getRoot(fim[y]))
            {
                printf("impossible\n");continue;
            }
            Evert(fim[x]);
            Access(fim[y]);
            splay(fim[y]);
            printf("%d\n",fim[y]->value);
        }
        if(s[0]==‘b‘)
        {
            int x=read();
            int y=read();
            if(getRoot(fim[x])==getRoot(fim[y]))
                puts("no");
            else
            {
                puts("yes");
                link(fim[x],fim[y]);
            }
        }
        if(s[0]==‘p‘)
        {
            int x=read(),y=read();
            Evert(fim[x]);fim[x]->w = y;
            fim[x]->Update();
        }
    }

}
时间: 2024-10-11 18:12:50

SPOJ - OTOCI LCT的相关文章

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

SPOJ QTREE3 lct裸题

题目链接 题意: 给定n个点 q个询问 下面n-1行给出树边,点有黑或白色,初始化为白色 下面q行: 询问有2种: 1. 0 x 把x点黑变白,白变黑 2.1 x 询问Path(1,x)路径上第一个黑点的点标, 若不存在黑点则输出-1 思路: lct裸题 #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #inc

【bzoj1180】[CROATIAN2009]OTOCI LCT

题目描述 给出n个结点以及每个点初始时对应的权值wi.起始时点与点之间没有连边.有3类操作: 1.bridge A B:询问结点A与结点B是否连通.如果是则输出"no".否则输出"yes",并且在结点A和结点B之间连一条无向边. 2.penguins A X:将结点A对应的权值wA修改为X. 3.excursion A B:如果结点A和结点B不连通,则输出"impossible".否则输出结点A到结点B的路径上的点对应的权值的和.给出q个操作,要

SPOJ QTREE2 lct裸题

题目链接 题意: 给一棵树,有边权 1.询问路径的边权和 2.询问沿着路径的第k个点标. 思路:lct裸题. #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #inclu

SPOJ QTREE2 lct

题目链接 题意: 给一棵树.有边权 1.询问路径的边权和 2.询问沿着路径的第k个点标. 思路:lct裸题. #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #inclu

SPOJ QTREE4 lct

题目链接 这个题已经处于花式tle了,改版后的spoj更慢了.. tle的话就多交几把... #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #include <s

SPOJ QTREE5 lct裸题

题目链接 对于每个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部最近的白点距离 rs:(链的下端点)距离链内部最近的白点距离 注意以上都是实边 虚边的信息用一个set维护. set维护的是对于每个不是链上,但是this的子树,那些子树中距离this最近的白点距离. #include <stdio.h> #include <string.h> #include <set> #include <algorithm> #include <i

SPOJ QTREE6 lct

题目链接 岛娘出的题.还是比較easy的 #include <iostream> #include <fstream> #include <string> #include <time.h> #include <vector> #include <map> #include <queue> #include <algorithm> #include <stack> #include <cstr

SPOJ QTREE5 lct

题目链接 对于每一个节点,记录这个节点所在链的信息: ls:(链的上端点)距离链内部近期的白点距离 rs:(链的下端点)距离链内部近期的白点距离 注意以上都是实边 虚边的信息用一个set维护. set维护的是对于每一个不是链上,可是this的子树,那些子树中距离this近期的白点距离. #include <stdio.h> #include <string.h> #include <set> #include <algorithm> #include <