首页 > 代码库 > uva 1479 - Graph and Queries(伸展树)
uva 1479 - Graph and Queries(伸展树)
题目链接:uva 1479 - Graph and Queries
题目大意:有一张m条边的无向图,每个节点都有一个权值,现在有若干个操作,
- D x:删除ID为x的节点
- Q x k:计算与节点x联通的节点当中,第k大的权值
- C x v:把节点x的权值改为v
解题思路:把所有操作反过来处理,先执行所有的D操作,获得最终的图,然后逆操作的时候对于D来说即为合并操作,Q和C则是查询和修改操作。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 20005;
const int maxm = 60005;
const int maxc = 500005;
// Union-Set
int f[maxn];
inline int getfar(int x) {
return x == f[x] ? x : f[x] = getfar(f[x]);
}
// Treap;
struct Node {
int val, rank, sum;
Node* cid[2];
Node (int val);
void maintain();
int cmp(int x);
};
Node* root[maxn];
void insert(Node* &o, int x);
void rotate(Node* &o, int d);
void remove(Node* &o, int x);
// Rank Tree;
void add_edge (int i);
void remove_tree(Node* &o);
void merge_tree(Node* &src, Node* & dest);
int rankth(Node* o, int k);
// Command;
struct Command {
char type;
int x, p;
}command[maxc];
bool flag[maxm];
ll tot, cnt;
int N, M, C, W[maxn], U[maxm], V[maxm];
void build () {
for (int i = 1; i <= N; i++) {
if (root[i] != NULL)
remove_tree(root[i]);
root[i] = new Node(W[i]);
}
for (int i = 1; i <= M; i++) {
if (!flag[i])
add_edge(i);
}
}
void init () {
C = 0;
memset(flag, 0, sizeof(flag));
for (int i = 1; i <= N; i++) {
f[i] = i;
scanf("%d", &W[i]);
}
for (int i = 1; i <= M; i++)
scanf("%d%d", &U[i], &V[i]);
int x, p;
char str[5];
while (scanf("%s", str) == 1 && str[0] != ‘E‘) {
scanf("%d", &x);
if (str[0] == ‘D‘) flag[x] = 1;
else if (str[0] == ‘Q‘) scanf("%d", &p);
else if (str[0] == ‘C‘) {
scanf("%d", &p);
swap(p, W[x]);
}
command[C++] = (Command){ str[0], x, p};
}
build();
}
void query (int x, int k) {
cnt++;
tot += rankth(root[getfar(x)], k);
}
void change (int x, int v) {
int u = getfar(x);
remove(root[u], W[x]);
insert(root[u], v);
W[x] = v;
}
int main () {
int cas = 0;
while (scanf("%d%d", &N, &M) == 2 && N) {
init();
tot = cnt = 0;
for (int i = C - 1; i >= 0; i--) {
char type = command[i].type;
if (type == ‘D‘)
add_edge(command[i].x);
else if (type == ‘Q‘)
query(command[i].x, command[i].p);
else
change(command[i].x, command[i].p);
}
printf("Case %d: %.6lf\n", ++cas, tot / (double) cnt);
}
return 0;
}
// Rank Tree;
int rankth(Node* o, int k) {
if (o == NULL || k <= 0 || k > o->sum)
return 0;
int s = (o->cid[1] == NULL ? 0 : o->cid[1]->sum);
if (k == s + 1) return o->val;
else if (k <= s) return rankth(o->cid[1], k);
else return rankth(o->cid[0], k - s - 1);
}
void remove_tree (Node* &o) {
for (int i = 0; i < 2; i++) {
if (o->cid[i] != NULL)
remove_tree(o->cid[i]);
}
delete o;
o = NULL;
}
void add_edge (int x) {
int u = getfar(U[x]), v = getfar(V[x]);
if (u != v) {
if (root[u]->sum < root[v]->sum)
swap(u, v);
f[v] = u;
merge_tree(root[v], root[u]);
}
}
void merge_tree (Node* &src, Node* &dest) {
for (int i = 0; i < 2; i++) {
if (src->cid[i] != NULL)
merge_tree(src->cid[i], dest);
}
insert(dest, src->val);
delete src;
src = http://www.mamicode.com/NULL;"hljs-comment" style="color:rgb(117,113,94)">// Treap
Node::Node (int val) {
sum = 1;
rank = rand();
this->val = val;
cid[0] = cid[1] = NULL;
}
void Node::maintain() {
sum = 1;
if (cid[0] != NULL) sum += cid[0]->sum;
if (cid[1] != NULL) sum += cid[1]->sum;
}
int Node::cmp(int x) {
if (val == x)
return -1;
return val < x ? 1 : 0;
}
void remove(Node* &o, int x) {
int d = o->cmp(x);
if (d == -1) {
Node* u = o;
if (o->cid[0] != NULL && o->cid[1] != NULL) {
int d2 = (o->cid[0]->rank > o->cid[1]->rank ? 1 : 0);
rotate(o, d2);
remove(o->cid[d2], x);
} else {
o = (o->cid[0] == NULL ? o->cid[1] : o->cid[0]);
delete u;
}
} else
remove(o->cid[d], x);
if (o != NULL)
o->maintain();
}
void rotate (Node* &o, int d) {
Node* k = o->cid[d^1];
o->cid[d^1] = k->cid[d];
k->cid[d] = o;
o->maintain();
k->maintain();
o = k;
}
void insert(Node* &o, int x) {
if (o == NULL)
o = new Node(x);
else {
int d = (x < o->val ? 0 : 1);
insert(o->cid[d], x);
if (o->cid[d]->rank > o->rank)
rotate(o, d^1);
}
o->maintain();
}uva 1479 - Graph and Queries(伸展树)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。