LA 5031


真正的勇士,敢于直面惨淡的人生,敢于正视淋漓的鲜血。” —–《记念刘和珍君》鲁迅


平衡树的启发式合并。

你们自己感受一下。

如果我写完暑假作业就来补题解。


#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值