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個操作,要求在線處理所有操作。數據範圍:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。

輸入格式

第一行包含一個整數n(1<=n<=30000),表示節點的數目。第二行包含n個整數,第i個整數表示第i個節點初始時對應的權值。第三行包含一個整數q(1<=n<=300000),表示操作的數目。以下q行,每行包含一個操作,操作的類別見題目描述。任意時刻每個節點對應的權值都是1到1000的整數。

輸出格式

輸出所有bridge操作和excursion操作對應的輸出,每個一行。

輸入樣例

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

輸出樣例

4

impossible

yes

6

yes

yes

15

yes

15

16

題解

LCT板題
但蒟蒻opt[0]打成了opt[1]查了一箇中午QAQ
對着黃學長代碼還是學會了更加簡化的LCT代碼
沒白弄

#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define isrt(u) !(e[e[u].f].ch[0] == u || e[e[u].f].ch[1] == u)
#define isr(u) (e[e[u].f].ch[1] == u)
#define ls e[u].ch[0]
#define rs e[u].ch[1]
using namespace std;
const int maxn = 30005,maxm = 100005,INF = 1000000000;
inline int RD(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
    return out * flag;
}
int N,M;
char opt[20];
struct node{int f,ch[2],w,sum,rev;}e[maxn];
void pup(int u){e[u].sum = e[ls].sum + e[u].w + e[rs].sum;}
void pd(int u){
    if (e[u].rev){
        swap(ls,rs);
        e[ls].rev ^= 1; e[rs].rev ^= 1; e[u].rev ^= 1;
    }
}
void push_down(int u){
    if (!isrt(u)) push_down(e[u].f);
    pd(u);
}
void spin(int u){
    int s = isr(u),fa = e[u].f;
    e[u].f = e[fa].f; if (!isrt(fa)) e[e[fa].f].ch[isr(fa)] = u;
    e[fa].ch[s] = e[u].ch[s ^ 1]; if (e[u].ch[s ^ 1]) e[e[u].ch[s ^ 1]].f = fa;
    e[fa].f = u; e[u].ch[s ^ 1] = fa;
    pup(fa); pup(u);
}
void splay(int u){
    push_down(u);
    for (; !isrt(u); spin(u))
        if (!isrt(e[u].f)) spin((isr(u) ^ isr(e[u].f)) ? u : e[u].f);
}
void Access(int u){
    for (int v = 0; u; u = e[v = u].f)
        splay(u),e[u].ch[1] = v,pup(u);
}
void Make_root(int u){Access(u); splay(u); e[u].rev ^= 1;}
int Getrt(int u){
    Access(u); splay(u);
    while (ls) u = ls;
    return u;
}
void Link(int u,int v){
    Make_root(u); e[u].f = v;
}
int Getsum(int u,int v){
    Make_root(u); Access(v); splay(v);
    return e[v].sum;
}
void solve1(int u,int v){
    if (Getrt(u) == Getrt(v)) puts("no");
    else puts("yes"),Link(u,v);
}
void solve2(int u,int v){
    Make_root(u);
    e[u].w = v; pup(u);
}
void solve3(int u,int v){
    if (Getrt(u) == Getrt(v)) printf("%d\n",Getsum(u,v));
    else puts("impossible");
}
int main(){
    N = RD(); REP(i,N) e[i].w = e[i].sum = RD();
    M = RD(); int u,v;
    while (M--){
        scanf("%s",opt); u = RD(); v = RD();
        if (opt[0] == 'b') solve1(u,v);
        else if (opt[0] == 'p') solve2(u,v);
        else solve3(u,v);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章