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
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
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 ",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); } } }