LA 5031

来源:互联网 发布:三国志9加优化补丁 编辑:程序博客网 时间:2024/04/29 02:29

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


平衡树的启发式合并。

你们自己感受一下。

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


#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 secondbool 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 checkint 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
原创粉丝点击