BZOJ_1180_[CROATIAN2009]OTOCI_LCT

BZOJ_1180_[CROATIAN2009]OTOCI_LCT

Description

给出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。

Input

第一行包含一个整数n(1<=n<=30000),表示节点的数目。
第二行包含n个整数,第i个整数表示第i个节点初始时对应的权值。
第三行包含一个整数q(1<=n<=300000),表示操作的数目。
以下q行,每行包含一个操作,操作的类别见题目描述。
任意时刻每个节点对应的权值都是1到1000的整数。

Output

输出所有bridge操作和excursion操作对应的输出,每个一行。

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

 LCT维护点权和,支持单点修改。
注意bridge操作是连通输出‘no'
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 30050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int ch[N][2],f[N],rev[N],sum[N],val[N],n,m;
char opt[20];
inline bool isrt(int p) {
    return ch[f[p]][0]!=p&&ch[f[p]][1]!=p;
}
inline void pushdown(int p) {
    if(rev[p]) {
        swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]);
        rev[ls]^=1; rev[rs]^=1; rev[p]=0;
    }
}
inline void pushup(int p) {
    sum[p]=sum[ls]+sum[rs]+val[p];
}
void update(int p) {
    if(!isrt(p)) update(f[p]);
    pushdown(p);
}
void rotate(int x) {
    int y=f[x],z=f[y],k=get(x);
    if(!isrt(y)) ch[z][ch[z][1]==y]=x;
    ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
    ch[x][!k]=y; f[y]=x; f[x]=z;
    pushup(y); pushup(x);
}
void splay(int x) {
    update(x);
    for(int fa;fa=f[x],!isrt(x);rotate(x))
        if(!isrt(fa))
            rotate(get(fa)==get(x)?fa:x);
}
void access(int p) {
    int t=0;
    while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
}
void makeroot(int p) {
    access(p); splay(p); swap(ls,rs); rev[p]^=1;
}
void link(int x,int p) {
    makeroot(x); splay(p); f[x]=p;
}
void cut(int x,int p) {
    makeroot(x); access(p); splay(p); ls=f[x]=0;
}
int find(int p) {
    access(p); splay(p);
    while(ls) pushdown(p),p=ls;
    return p;
}
void fix(int p,int v) {
    access(p); splay(p); val[p]=v; pushup(p);
}
int main() {
    scanf("%d",&n);
    int i,x,y;
    for(i=1;i<=n;i++) scanf("%d",&val[i]);
    scanf("%d",&m);
    for(i=1;i<=m;i++) {
        scanf("%s%d%d",opt,&x,&y);
        if(opt[0]=='e') {
            int t1=find(x),t2=find(y);
            if(t1!=t2) {
                puts("impossible");
            }
            else {
                makeroot(x); access(y); splay(y);
                printf("%d\n",sum[y]);
            }
        }else if(opt[0]=='b') {
            int t1=find(x),t2=find(y);
            if(t1==t2) puts("no");
            else {
                puts("yes"); link(x,y);
            }
        }else {
            fix(x,y);
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/suika/p/8967917.html