题目连接
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3032
完全照着大白抄的,没什么好说的。。
不过一个地方打错了,RE了好久%>_<%
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<cstdlib>
using namespace std;
#define inf 0x3f3f3f3f
#define eps 1e-8
#define LL long long
#define ULL unsigned long long
#define MP make_pair
const int mxc = 1000000 + 10;
const int mxn = 200000 + 10;
const int mxm = 600000 + 10;
struct node {
node *ch[10];
int r, v, s;
node( int v ): v( v ) {
ch[0] = ch[1] = NULL;
r = rand();
s = 1;
}
bool operator < ( const node &b ) const {
return r < b.r;
}
int cmp( int x ) const {
if( v == x )
return -1;
return x < v ? 0 : 1;
}
void mt() {
s = 1;
if( ch[0] )
s += ch[0] -> s;
if( ch[1] )
s += ch[1] -> s;
}
};
void rt( node *&o, int d ) {
node *k = o -> ch[d^1];
o -> ch[d^1] = k -> ch[d];
k -> ch[d] = o;
o -> mt();
k -> mt();
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 ) {
rt( o, d ^ 1 );
}
}
o -> mt();
}
void remove( node *&o, int x ) {
int d = o -> cmp( x );
if( d == -1 ) {
node *u = o;
if( o -> ch[0] && o -> ch[1] ) {
int d2 = ( o -> ch[0] -> r > o -> ch[1] -> r ? 1 : 0 );
rt( 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 )
o -> mt();
}
struct Com {
char type;
int x, p;
Com(){}
Com( char type, int x, int p ): type( type ), x( x ), p( p ) {}
}com[mxc];
int n, m, w[mxn], from[mxm], to[mxm], vis[mxm];
int fa[mxn];
int findset( int x ) {
if( fa[x] != x )
fa[x] = findset( fa[x] );
return fa[x];
}
node *root[mxn];
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( k == s + 1 )
return o -> v;
if( k <= s )
return kth( o -> ch[1], k );
return kth( o -> ch[0], k - s - 1 );
}
void merge( node *&i, node *&j ) {
if( i -> ch[0] )
merge( i -> ch[0], j );
if( i -> ch[1] )
merge( i -> ch[1], j );
insert( j, i -> v );
delete i;
i = NULL;
}
void removetree( node *& x ) {
if( x -> ch[0] )
removetree( x -> ch[0] );
if( x -> ch[1] )
removetree( x -> ch[1] );
delete x;
x = NULL;
}
void add_edge( int x ) {
int u = findset( from[x] ), v = findset( to[x] );
if( u != v ) {
if( root[u] -> s < root[v] -> s ) {
fa[u] = v;
merge( root[u], root[v] );
}
else {
fa[v] = u;
merge( root[v], root[u] );
}
}
}
int qc;
LL qt;
void query( int x, int k ) {
qc ++;
qt += kth( root[findset(x)], k );
}
void update( int x, int v ) {
int u = findset( x );
remove( root[u], w[x] );
insert( root[u], v );
w[x] = v;
}
int main() {
int cas = 0;
while( scanf( "%d%d", &n, &m ) == 2 && n ) {
for( int i = 1; i <= n; ++i )
scanf( "%d", &w[i] );
for( int i = 1; i <= m; ++i )
scanf( "%d%d", &from[i], &to[i] );
memset( vis, 0, sizeof( vis ) );
int c = 0;
while( 1 ) {
char type;
int x, p = 0, v = 0;
scanf( " %c", &type );
if( type == 'E' )
break;
scanf( "%d", &x );
if( type == 'D' )
vis[x] = 1;
if( type == 'Q' )
scanf( "%d", &p );
if( type == 'C' ) {
scanf( "%d", &v );
p = w[x];
w[x] = v;
}
Com tem( type, x, p );
com[c++] = tem;
}
for( int i = 1; i <= n; ++i ) {
fa[i] = i;
if( root[i] )
removetree( root[i] );
root[i] = new node( w[i] );
}
for( int i = 1; i <= m; ++i )
if( !vis[i] )
add_edge( i );
qt = qc = 0;
for( int i = c - 1; i >= 0; -- i ) {
if( com[i].type == 'D' )
add_edge( com[i].x );
if( com[i].type == 'Q' )
query( com[i].x, com[i].p );
if( com[i].type == 'C' )
update( com[i].x, com[i].p );
}
printf( "Case %d: %.6lf\n", ++cas, qt / ( double ) qc );
}
return 0;
}