您的位置:首页 > 产品设计 > UI/UE

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

2015-09-01 15:29 525 查看
题意:

。。。

同样收录在 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: