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 5Sample Output
4
impossible
yes
6
yes
yes
15
yes
15
16
看起来就是LCT啊..
求和x到y的伪代码:
getsum(x,y)
access(x) splay(x) rev[x]^=1
access(y) splay(y)
reutrn sum[y]
修改权值的伪代码:
change(x,k)
access(x) splay(x) rev[x]^=1
val[x]=k
update(x)
那么就是很显而易见的标算了啊..
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int Maxn = 30010;
int val[Maxn], sum[Maxn], c[Maxn][2], rev[Maxn], fa[Maxn];
int n, m;
char s[11];
bool is_root ( int x ){ return c[fa[x]][0] != x && c[fa[x]][1] != x; }
void update ( int x ){
int lc = c[x][0], rc = c[x][1];
sum[x] = sum[lc]+val[x]+sum[rc];
}
void push_down ( int x ){
if ( rev[x] ){
rev[x] = 0;
int lc = c[x][0], rc = c[x][1];
swap ( c[x][0], c[x][1] );
rev[lc] ^= 1; rev[rc] ^= 1;
}
}
int st[Maxn], tp;
void prep ( int x ){
tp = 0; int i;
for ( i = x; !is_root (i); i = fa[i] ) st[++tp] = i;
st[++tp] = i;
for ( i = tp; i >= 1; i -- ) push_down (st[i]);
}
void rotate ( int x ){
int y = fa[x], z = fa[y], l, r;
if ( c[y][0] == x ) l = 0; else l = 1; r = l^1;
if ( !is_root (y) ){ if ( c[z][0] == y ) c[z][0] = x; else c[z][1] = x; }
fa[x] = z; fa[y] = x; fa[c[x][r]] = y;
c[y][l] = c[x][r]; c[x][r] = y;
update (y); update (x);
}
void splay ( int x ){
prep (x);
while ( !is_root (x) ){
int y = fa[x], z = fa[y];
if ( !is_root (y) ){
if ( (c[y][0]==x)^(c[z][0]==y) ) rotate (x);
rotate (y);
}
rotate (x);
}
}
void access ( int x ){
int t = 0;
while (x){
splay (x);
c[x][1] = t;
update (x);
t = x;
x = fa[x];
}
}
int find_root ( int x ){
access (x);
splay (x);
while (c[x][0]) x = c[x][0];
return x;
}
void make_root ( int x ){ access (x); splay (x); rev[x] ^= 1; }
void link ( int x, int y ){ make_root (x); fa[x] = y; }
int get_sum ( int x, int y ){
make_root (x);
access (y); splay (y);
return sum[y];
}
void change ( int x, int k ){
make_root (x);
val[x] = k;
update (x);
}
int main (){
int i, j, k;
scanf ( "%d", &n );
for ( i = 1; i <= n; i ++ ){ scanf ( "%d", &val[i] ); sum[i] = val[i]; }
scanf ( "%d", &m );
for ( i = 1; i <= m; i ++ ){
getchar ();
scanf ( "%s", s+1 );
int x, y;
scanf ( "%d%d", &x, &y );
if ( s[1] == 'b' ){
if ( find_root (x) == find_root (y) ) printf ( "no\n" );
else { printf ( "yes\n" ); link ( x, y ); }
}
else if ( s[1] == 'p' ) change ( x, y );
else {
if ( find_root (x) != find_root (y) ) printf ( "impossible\n" );
else printf ( "%d\n", get_sum ( x, y ) );
}
}
return 0;
}