传送门:【UVALive】5031 Graph and Queries
题目分析:第一道treap~yeah
代码如下:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std ;
#define REP( i , a , b ) for ( int i = a ; i < b ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
typedef long long LL ;
const int MAXN = 20005 ;
const int MAXL = 60005 ;
const int MAXC = 500005 ;
struct Node {
Node *ch[2] ;
int r ;
int v ;
int s ;
Node ( int v = 0 ) : v ( v ) {
ch[0] = ch[1] = NULL ;
r = rand () ;
s = 1 ;
}
int cmp ( int x ) {
return x == v ? -1 : ( x < v ? 0 : 1 ) ;
}
void maintain () {
s = 1 ;
if ( ch[0] != NULL )
s += ch[0] -> s ;
if ( ch[1] != NULL )
s += ch[1] -> s ;
}
} ;
struct Line {
int u , v ;
void input () {
scanf ( "%d%d" , &u , &v ) ;
}
} ;
struct Command {
char type ;
int x , v ;
Command () {}
Command ( char type , int x , int v ) : type ( type ) , x ( x ) , v ( v ) {}
} ;
Node *root[MAXN] ;
Line line[MAXL] ;
Command command[MAXC] ;
int weight[MAXN] ;
int n , m , q ;
int p[MAXN] ;
int move[MAXL] ;
int query_cnt ;
LL query_tot ;
void rotate ( Node *&o , int d ) {
Node *k = o -> ch[d ^ 1] ;
o -> ch[d ^ 1] = k -> ch[d] ;
k -> ch[d] = o ;
o -> maintain () ;
k -> maintain () ;
o = k ;
}
void insert ( Node *&o , int x ) {
if ( o == NULL ) {
o = new Node ( x ) ;
} else {
int d = x < o -> v ? 0 : 1 ;
insert ( o -> ch[d] , x ) ;
if ( o -> ch[d] -> r > o -> r )
rotate ( o , d ^ 1 ) ;
}
o -> maintain () ;
}
void remove ( Node *&o , int x ) {
int d = o -> cmp ( x ) ;
if ( d == -1 ) {
Node *u = o ;
if ( o -> ch[0] != NULL && o -> ch[1] != NULL ) {
int d2 = o -> ch[0] -> r > o -> ch[1] -> r ? 1 : 0 ;
rotate ( o , d2 ) ;
remove ( o -> ch[d2] , x ) ;
} else {
if ( o -> ch[0] == NULL )
o = o -> ch[1] ;
else
o = o -> ch[0] ;
delete u ;
}
} else
remove ( o -> ch[d] , x ) ;
if ( o != NULL )
o -> maintain () ;
}
void remove_tree ( Node *&o ) {
if ( o -> ch[0] != NULL )
remove_tree ( o -> ch[0] ) ;
if ( o -> ch[1] != NULL )
remove_tree ( o -> ch[1] ) ;
delete o ;
o = NULL ;
}
int find ( int x ) {
return p[x] == x ? x : ( p[x] = find ( p[x] ) ) ;
}
void merge ( Node *&src , Node *&des ) {
if ( src -> ch[0] != NULL )
merge ( src -> ch[0] , des ) ;
if ( src -> ch[1] != NULL )
merge ( src -> ch[1] , des ) ;
insert ( des , src -> v ) ;
delete src ;
src = NULL ;
}
void add_edge ( int i ) {
int x = find ( line[i].u ) ;
int y = find ( line[i].v ) ;
if ( x != y ) {
if ( root[x] -> s < root[y] -> s ) {
p[x] = y ;
merge ( root[x] , root[y] ) ;
} else {
p[y] = x ;
merge ( root[y] , root[x] ) ;
}
}
}
void modify ( int x , int v ) {
int o = find ( x ) ;
remove ( root[o] , weight[x] ) ;
insert ( root[o] , v ) ;
weight[x] = v ;
}
int kth ( Node *o , int k ) {
if ( o == NULL || k <= 0 || k > o -> s )
return 0 ;
int s = o -> ch[1] == NULL ? 0 : o -> ch[1] -> s ;
if ( s + 1 == k )
return o -> v ;
else {
if ( s >= k )
return kth ( o -> ch[1] , k ) ;
else
return kth ( o -> ch[0] , k - s - 1 ) ;
}
}
void query ( int x , int k ) {
x = find ( x ) ;
++ query_cnt ;
query_tot += kth ( root[x] , k ) ;
}
void init () {
query_cnt = 0 ;
query_tot = 0 ;
CLR ( move , 0 ) ;
}
void build () {
FOR ( i , 1 , n )
scanf ( "%d" , &weight[i] ) ;
FOR ( i , 1 , m )
line[i].input () ;
for ( q = 0 ; ; ++ q ) {
char type ;
int x , v , next_weight ;
scanf ( " %c" , &type ) ;
if ( type == 'E' )
break ;
scanf ( "%d" , &x ) ;
if ( type == 'D' )
move[x] = 1 ;
if ( type == 'Q' )
scanf ( "%d" , &v ) ;
if ( type == 'C' ) {
scanf ( "%d" , &next_weight ) ;
v = weight[x] ;
weight[x] = next_weight ;
}
command[q] = Command ( type , x , v ) ;
}
FOR ( i , 1 , n ) {
p[i] = i ;
if ( root[i] != NULL )
remove_tree ( root[i] ) ;
root[i] = new Node ( weight[i] ) ;
}
FOR ( i , 1 , m )
if ( !move[i] )
add_edge ( i ) ;
}
void solve () {
init () ;
build () ;
REV ( i , q - 1 , 0 ) {
if ( command[i].type == 'D' )
add_edge ( command[i].x ) ;
if ( command[i].type == 'Q' )
query ( command[i].x , command[i].v ) ;
if ( command[i].type == 'C' )
modify ( command[i].x , command[i].v ) ;
}
printf ( "%.6f\n" , ( double ) query_tot / query_cnt ) ;
}
int main () {
int cas = 0 ;
while ( ~scanf ( "%d%d" , &n , &m ) && ( n || m ) ) {
printf ( "Case %d: " , ++ cas ) ;
solve () ;
}
return 0 ;
}