uva live 5031 Graph and Queries(Treap x 并查集)

题意:
。。。
同样收录在 HDU 3726,不过hdu貌似有时候 re 会报 wa,不方便调错。。
思路:
教科书题。。
用来练 Treap 模板很合适

尝试写了几发GC, 用stack来装指针。。发现效率都不是很高。。还很耗内存。。于是放弃了。。

// 纯动态
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <set>
#include <queue>
#include <map>
#include <cmath>
#include <cassert>
#include <stack>
#include <stdexcept>
using namespace std;
#define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i))
const int N = 20000 + 5;
typedef long long LL;

struct Node {
    Node* ch[2];
    int fix, key, cnt, sz;

    inline void update() {
        sz = cnt + ch[0]->sz + ch[1]->sz;
    }

    inline bool lt(int other) const {
        return key < other;
    }
} *nil;

Node* allocate_node(int key) {
    Node* nd = new Node();
    nd->ch[0] = nd->ch[1] = nil;
    nd->sz = nd->cnt = 1;
    nd->key = key;
    nd->fix = rand();
    return nd;
}

void free_node(Node* rt) {
    if ( rt->ch[0] != nil ) free_node(rt->ch[0]);
    if ( rt->ch[1] != nil ) free_node(rt->ch[1]);
    delete rt;
}

// d: 0 - right rotate, 1 - left rotate
void Rot(Node* &rt, int d) {
    Node *t = rt->ch[d];
    rt->ch[d] = t->ch[1^d];
    t->ch[1^d] = rt;
    rt->update();
    t->update();
    rt = t;
}

void Insert(Node* &rt, int key) {
    if ( rt != nil ) {
        if ( key == rt->key ) {
            ++ rt->cnt;
        } else {
            int d = rt->lt(key); // insert into ch[d]
            Insert(rt->ch[d], key);
            if ( rt->ch[d]->fix < rt->fix ) Rot(rt, d);
        }

    } else {
        rt = allocate_node(key);
    }
    rt->update();
}

void Erase(Node* &rt, int key) {
    if ( rt != nil ) {
        if ( rt->key == key ) {
            if ( rt->cnt > 1 ) {
                -- rt->cnt;
            } else {
                if ( rt->ch[0] == nil && rt->ch[1] == nil  ) {
                    rt = nil; return;
                } else {
                    int d = rt->ch[0]->fix > rt->ch[1]->fix;
                    Rot(rt, d);
                    Erase(rt->ch[1^d], key);
                }
            }
        } else {
            int d = rt->lt(key);
            Erase(rt->ch[d], key);
        }
        rt->update();
    } else {
        //cout << "not found" << endl;
    }
}

int GetKth(const Node* rt, int k) {
    if ( k <= rt->ch[0]->sz )
        return GetKth(rt->ch[0], k);
    k -= rt->ch[0]->sz + rt->cnt;
    if ( k <= 0 )
        return rt->key;
    if ( k <= rt->ch[1]->sz )
        return GetKth(rt->ch[1], k);
    else {
        //throw runtime_error("k is larger than size");
        while (1);
    }
}

void MergeTo(Node* src, Node* &dst) {
    if ( src == nil ) return;
    queue<Node*> q;
    q.push(src);
    while ( !q.empty() ) {
        Node* u = q.front(); q.pop();
        for(int i = 0; i < u->cnt; ++ i) Insert(dst, u->key);
        if ( u->ch[0] != nil ) q.push(u->ch[0]);
        if ( u->ch[1] != nil ) q.push(u->ch[1]);
    }
    free_node(src);
}

void treap_global_init() {
    nil = new Node();
    memset(nil, 0, sizeof(Node));
    nil->fix = INT_MAX;
}

const int MaxV = 2e4 + 5, MaxE = 6e4 + 5;

struct Op {
    char type;
    int x, y;
} ops[500005];

int weight[MaxV], can[MaxE], edges[MaxE][2];
Node *tr[MaxV];

namespace UF {
    int pa[MaxV];

    void init(int n) {
        rep(i, 0, n-1) pa[i] = i;
    }

    int find(int x) {
        return x == pa[x] ? x : pa[x] = find(pa[x]);
    }

    void Union(int x, int y, int ctl = 0) {
        int px = find(x), py = find(y);
        if ( px != py ) {
            if ( tr[px]->sz > tr[py]->sz ) {
                if ( ctl )  {
                    MergeTo(tr[py], tr[px]);
                }
                pa[py] = px;
            } else {
                if ( ctl ) {
                    MergeTo(tr[px], tr[py]);
                }
                pa[px] = py;
            }
        }
    }
};

int main() {
#ifdef _LOCA_ENV_
    freopen("input.in", "r", stdin);
#endif // _LOCA_ENV
    /// treap init ///
    treap_global_init();
    /// start here ///
    int n, m, cas = 0;
    while ( scanf("%d%d", &n, &m) != EOF && n ) {
        rep(i, 0, n-1) scanf("%d", weight + i);
        rep(i, 0, m-1) {
            can[i] = 1;
            scanf("%d%d", &edges[i][0], &edges[i][1]);
            -- edges[i][0], -- edges[i][1];
        }
        int onm = 0;
        while ( 1 ) {
            char op;
            int x, y, z;
            for (op = getchar(); op == ' ' || op == '\n'; op = getchar());
            ops[onm].type = op;
            if ( op == 'D' ) {
                scanf("%d", &x);
                -- x;
                ops[onm].x = x;
                can[x] = 0;
            } else if ( op == 'Q' ) {
                scanf("%d%d", &x, &y);
                -- x;
                ops[onm].x = x;
                ops[onm].y = y;
            } else if ( op == 'C' ) {
                scanf("%d%d", &x, &y);
                -- x;
                ops[onm].x = x;
                ops[onm].y = weight[x];
                weight[x] = y;
            } else
                break;
            ++ onm;
        }

        UF::init(n);
        rep(i, 0, n-1) {
            tr[i] = nil;
            Insert(tr[i], weight[i]);
        }
        rep(i, 0, m-1) if ( can[i] ) UF::Union(edges[i][0], edges[i][1], 1);

        double tot = 0, qnm = 0;;
        for (int o = onm - 1; o >= 0; -- o) {
            int tmp = -1;
            if ( ops[o].type == 'Q' ) {
                int x = UF::find(ops[o].x);
                //cout << " root " << x  << " , "<< tr[x].size() << endl;
                if ( ops[o].y >= 1 && ops[o].y <= tr[x]->sz ) {
                    tmp = GetKth(tr[x], tr[x]->sz + 1 - ops[o].y);
                    tot += tmp;
                }
                qnm += 1;
            } else if ( ops[o].type == 'C' ) {
                int x = UF::find(ops[o].x);
                Erase(tr[x], weight[ops[o].x]);
                Insert(tr[x], ops[o].y);
                weight[ops[o].x] = ops[o].y;
            } else if ( ops[o].type == 'D' ) {
                int u = edges[ops[o].x][0], v = edges[ops[o].x][1];
                UF::Union(u, v, 1);
            }
        }
        double ans = tot / qnm;
        printf("Case %d: %.6f\n", ++ cas, ans);

        rep(i, 0, n-1) {
            int x = UF::find(i);
            if ( tr[x] != nil ) {
                free_node(tr[x]);
                tr[x] = nil;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值