“真正的勇士,敢于直面惨淡的人生,敢于正视淋漓的鲜血。” —–《记念刘和珍君》鲁迅
平衡树的启发式合并。
你们自己感受一下。
如果我写完暑假作业就来补题解。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <utility>
#include <iostream>
#include <algorithm>
template<class Num>void read(Num &x)
{
char c; int flag = 1;
while((c = getchar()) < '0' || c > '9')
if(c == '-') flag *= -1;
x = c - '0';
while((c = getchar()) >= '0' && c <= '9')
x = (x<<3) + (x<<1) + (c-'0');
x *= flag;
return;
}
template<class Num>void write(Num x)
{
if(x < 0) putchar('-'), x = -x;
static char s[20];int sl = 0;
while(x) s[sl++] = x%10 + '0',x /= 10;
if(!sl) {putchar('0');return;}
while(sl) putchar(s[--sl]);
}
const int maxm = 60050, maxn = 20050;
const int opsize = (200050 << 1) + maxm;
#define REP(__i,__start,__end) for(int __i = (__start); __i <= (__end); __i++)
int type[opsize], opx[opsize], opy[opsize], opl;
int w[maxn], n, m, cnt;
long long ans;
std::pair<int,int> edge[maxm];
#define Vx first
#define Vy second
bool hash[maxm];
int _fa[maxn], fa[maxn], c[maxn][2], sz[maxn];
#define check(x) (x)
void update(int a)
{
sz[a] = sz[c[a][0]] + sz[c[a][1]] + 1;
}
void rotate(int x)
{
int y = fa[x], z = fa[y], i, j;
j = (c[z][1] == y), i = (c[y][1] == x);
if(check(z)) c[z][j] = x;
if(c[x][i^1]) fa[c[x][i^1]] = y;
fa[x] = z, fa[y] = x;
c[y][i] = c[x][i^1], c[x][i^1] = y;
update(y), update(x);
}
void Splay(int v)
{
int g = fa[v], h = fa[g];
while(check(g))
{
if(check(h))
{
if((c[h][1] == g)^(c[g][1] == v))
rotate(v);
else
rotate(g);
}
rotate(v), g = fa[v], h = fa[g];
}
update(v);
}
#undef check
int ask(int k,int now)
{
while(true)
{
int L = c[now][0];
if(k <= sz[L]) now = L;
else if(k > sz[L] + 1) k -= sz[L] + 1, now = c[now][1];
else return now;
}
return now;
}
void _insert(int x,int now)
{
c[x][0] = c[x][1] = 0;
fa[x] = 0, sz[x] = 1;
if(!now) return;
Splay(now);
while(true)
{
if(w[x] <= w[now])
{
if(c[now][0])
now = c[now][0];
else
{
c[now][0] = x;
fa[x] = now;
break;
}
}
else
{
if(c[now][1])
now = c[now][1];
else
{
c[now][1] = x;
fa[x] = now;
break;
}
}
}
Splay(x);
}
int _delete(int x)
{
Splay(x);
if(sz[x] == 1) return 0;
if(c[x][1])
{
int r = ask((sz[c[x][0]] + 1) + 1, x);
fa[c[x][1]] = 0, Splay(r);
c[r][0] = c[x][0];
fa[c[x][0]] = r;
update(r);
return r;
}
else
{
fa[c[x][0]] = 0;
return c[x][0];
}
}
void fill(int now,int arr[])
{
int f = 1, r = 1;
arr[r++] = now;
while(f != r)
{
int x = arr[f++];
if(c[x][0]) arr[r++] = c[x][0];
if(c[x][1]) arr[r++] = c[x][1];
}
}
int all[maxn];
void merge(int x,int y)
{
Splay(x), Splay(y);
if(sz[x] > sz[y]) std::swap(x, y);
int szm = sz[x], f = y;
fill(x, all);
REP(i, 1, szm) _insert(all[i], f), f = all[i];
}
int query(int k,int x)
{
Splay(x); if(k > sz[x] || k < 1) return 0;
int r = ask(sz[x] - k + 1, x); Splay(r); return w[r];
}
int find(int x)
{
return _fa[x] == x ? x : (_fa[x] = find(_fa[x]));
}
void init()
{
int u, v;
char s[3];
cnt = ans = opl = 0;
REP(i, 1, m) hash[i] = false;
REP(i, 1, n) read(w[i]);
REP(i, 1, m)
{
read(u), read(v);
edge[i] = std::make_pair(u, v);
}
while(scanf("%s", s) != EOF)
{
if(s[0] == 'E') break;
++opl;
if(s[0] == 'D')
{
type[opl] = 1;
read(opx[opl]);
hash[opx[opl]] = true;
}
else if(s[0] == 'Q')
{
type[opl] = 2;
read(opx[opl]), read(opy[opl]);
}
else if(s[0] == 'C')
{
type[opl] = 3;
read(opx[opl]), read(opy[opl]);
std::swap(w[opx[opl]], opy[opl]);
}
else break;
}
}
void solve()
{
int x, y;
REP(i, 1, n)
{
_fa[i] = i, sz[i] = 1;
c[i][0] = c[i][1] = 0;
fa[i] = 0, sz[i] = 1;
}
REP(i, 1, m)
if(!hash[i])
{
x = find(edge[i].Vx);
y = find(edge[i].Vy);
if(x != y)
{
_fa[x] = y;
merge(x, y);
}
}
for(int i = opl; i >= 1; i--)
{
if(type[i] == 1)
{
x = find(edge[opx[i]].Vx);
y = find(edge[opx[i]].Vy);
if(x != y)
{
_fa[x] = y;
merge(x, y);
}
}
else if(type[i] == 2)
{
++cnt, ans += query(opy[i], opx[i]);
}
else if(type[i] == 3)
{
x = _delete(opx[i]);
w[opx[i]] = opy[i];
_insert(opx[i], x);
}
else break;
}
printf("%.6lf\n",(double)ans/cnt);
}
int main()
{
int CaseNum = 0;
#ifndef ONLINE_JUDGE
freopen("C.in","r",stdin);
freopen("C.out","w",stdout);
#endif
while(true)
{
read(n), read(m);
if(!(n + m)) break;
++CaseNum;
printf("Case %d: ",CaseNum);
init(), solve();
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}