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

来源:互联网 发布:统计型定位算法模型 编辑:程序博客网 时间:2024/05/22 13:52

题意:
。。。
同样收录在 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 rotatevoid 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