离线做法,逆序执行操作,那么原本的删除边的操作变为加入边的操作,用名次树维护每一个连通分量的名次,加边操作即是连通分量合并操作,每次将结点数小的子树向结点数大的子树合并,那么单次合并复杂度O(n1logn2),由于合并之后原本结点数少的子树结点数至少翻倍,所以每个结点最多被插入 logn 次,故总时间复杂度为

O(n log2n)  。

注意细节处理,代码如下:

 #include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector> using namespace std; struct Node {
Node *ch[];
int r;
int v;
int s;
Node(int vv): v(vv) {
s = ;
ch[] = ch[] = NULL;
r = rand();
}
int cmp(int x) const {
if(x == v) return -;
return x < v ? : ;
}
void maintain() {
s = ;
if(ch[] != NULL) s += ch[]->s;
if(ch[] != NULL) s += ch[]->s;
}
}; void rotate(Node* &o, int d) {
Node* k = o->ch[d^]; o->ch[d^] = k->ch[d]; k->ch[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->v ? : ;
insert(o->ch[d], x);
if(o->ch[d]->r > o->r) rotate(o, d^);
}
o->maintain();
}
void remove(Node* &o, int x) {
int d = o->cmp(x);
Node* u = o;
if(d == -) {
if(o->ch[] != NULL && o->ch[] != NULL){
int d2 = o->ch[]->r > o->ch[]->r ? : ;
rotate(o, d2);
remove(o->ch[d2], x);
}
else {
if(o->ch[] == NULL) o = o->ch[]; else o = o->ch[];
delete u;
}
}
else remove(o->ch[d], x);
if(o != NULL) o->maintain();
} int kth(Node* o, int k) {
if(o == NULL || k > o->s || k <= ) return ;
int s = o->ch[] == NULL ? : o->ch[]->s;
if(k == s+) return o->v;
else if(k <= s) return kth(o->ch[], k);
else return kth(o->ch[], k-s-);
} struct cmd {
char type;
int x, p;
}; vector<cmd> cmds; const int maxn = 2e4 + ;
const int maxm = 6e4 + ;
int n, m;
int weight[maxn], from[maxm], to[maxm], removed[maxm]; int pa[maxn];
int findpa(int x) {return x == pa[x] ? x : pa[x] = findpa(pa[x]);}
long long sum;
int cnt;
Node* root[maxn]; void mergetreeto(Node* &ser, Node* &to) {
if(ser->ch[] != NULL) mergetreeto(ser->ch[], to);
if(ser->ch[] != NULL) mergetreeto(ser->ch[], to);
insert(to, ser->v);
delete ser;
ser = NULL;
} void removetree(Node *&ser) {
if(ser == NULL) return;
if(ser->ch[] != NULL) removetree(ser->ch[]);
if(ser->ch[] != NULL) removetree(ser->ch[]);
delete ser;
ser = NULL;
} void add_edge(int id) {
int x = findpa(pa[from[id]]);
int y = findpa(pa[to[id]]);
if(x != y) {
if(root[x]->s < root[y]->s) mergetreeto(root[x], root[y]), pa[x] = y;
else mergetreeto(root[y], root[x]), pa[y] = x;
}
} void querycnt(int x, int k) {
cnt++;
sum += kth(root[findpa(x)], k);
} void change_w(int x, int v) {
int u = findpa(pa[x]);
remove(root[u], weight[x]);
insert(root[u], v);
weight[x] = v;
} void init() {
cmds.clear();
cnt = ;
sum = ;
memset(removed, , sizeof removed);
for(int i = ; i < n; i++) removetree(root[i]);
}
int main() {
int kase = ;
while(scanf("%d%d", &n, &m) == && n) {
for(int i = ; i <= n; i++) scanf("%d", &weight[i]);
for(int i = ; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
from[i] = u;
to[i] = v;
}
init();
while() {
getchar();
char ch;
scanf("%c", &ch);
cmd C;
C.type = ch;
C.x = C.p = ;
if(ch == 'E') break;
scanf("%d", &C.x);
if(ch == 'D') removed[C.x] = ;
if(ch == 'Q') scanf("%d", &C.p);
if(ch == 'C') {
scanf("%d", &C.p);
swap(C.p, weight[C.x]);
}
cmds.push_back(C);
}
for(int i = ; i <= n; i++) {
pa[i] = i;
root[i] = new Node(weight[i]);
}
for(int i = ; i <= m; i++)
if(!removed[i]) add_edge(i); for(int i = cmds.size()-; i >= ; i--) {
cmd C = cmds[i];
if(C.type == 'D') add_edge(C.x);
if(C.type == 'C') change_w(C.x, C.p);
if(C.type == 'Q') querycnt(C.x, C.p);
}
printf("Case %d: %.6lf\n", ++kase, sum/double(cnt));
}
return ;
}

LA 5031 Graph and Queries —— Treap名次树的更多相关文章

  1. LA - 5031 - Graph and Queries

    题意:一个N个点(编号从1开始),M条边的无向图(编号从1开始),有3种操作: D X:把编号为X的边删了: Q X K:查询编号为X的结点所在连通分量第K大的元素: C X V:将编号为X的结点的权 ...

  2. UVaLive 5031 Graph and Queries (Treap)

    题意:初始时给出一个图,每个点有一个权值,三种操作:(1)删除某个边:(2)修改每个点的权值:(3)询问与节点x在一个连通分量中所有点的第K大的权值. 析:首先是要先离线,然后再倒着做,第一个操作就成 ...

  3. uvalive 5031 Graph and Queries 名次树+Treap

    题意:给你个点m条边的无向图,每个节点都有一个整数权值.你的任务是执行一系列操作.操作分为3种... 思路:本题一点要逆向来做,正向每次如果删边,复杂度太高.逆向到一定顺序的时候添加一条边更容易.详见 ...

  4. UVa 1479 (Treap 名次树) Graph and Queries

    这题写起来真累.. 名次树就是多了一个附加信息记录以该节点为根的树的总结点的个数,由于BST的性质再根据这个附加信息,我们可以很容易找到这棵树中第k大的值是多少. 所以在这道题中用一棵名次树来维护一个 ...

  5. HDU 3726 Graph and Queries treap树

    题目来源:HDU 3726 Graph and Queries 题意:见白书 思路:刚学treap 參考白皮书 #include <cstdio> #include <cstring ...

  6. 「模板」「讲解」Treap名次树

    Treap实现名次树 前言 学平衡树的过程可以说是相当艰难.浏览Blog的过程中看到大量指针版平衡树,不擅长指针操作的我已经接近崩溃.于是,我想着一定要写一篇非指针实现的Treap的Blog. 具体如 ...

  7. UVALive 5031 Graph and Queries (Treap)

    删除边的操作不容易实现,那么就先离线然后逆序来做. 逆序就变成了合并,用并存集判断连通,用Treap树来维护一个连通分量里的名次. Treap = Tree + Heap.用一个随机的优先级来平衡搜索 ...

  8. UVALive - 5031 Graph and Queries (并查集+平衡树/线段树)

    给定一个图,支持三种操作: 1.删除一条边 2.查询与x结点相连的第k大的结点 3.修改x结点的权值 解法:离线倒序操作,平衡树or线段树维护连通块中的所有结点信息,加个合并操作就行了. 感觉线段树要 ...

  9. UVALive5031 Graph and Queries(Treap)

    反向操作,先求出最终状态,再反向操作. 然后就是Treap 的合并,求第K大值. #include<cstdio> #include<iostream> #include< ...

随机推荐

  1. java 将word转为PDF (100%与word软件转换一样)

    jdk环境:jdk_8.0.1310.11_64    (64位) 1.引入pom文件 <!-- word转pdf(依赖windows本地的wps) --> <dependency& ...

  2. Docker.[1].环境准备.

    Docker.[1].环境准备. 环境描述: 在笔记本中安装了虚拟机,虚拟机中又安装了RedHat 7.x操作系统,然后在这个RedHat7.x的操作系统上,进行安装Docker. 虚拟机中的操作系统 ...

  3. JVM学习篇章(一)

    熟悉Java开发的同学,应该都知道jvm是什么,---它就是Java虚拟机,今天我们就学习一下:  内存分配原则:  常用的监控命令

  4. python ddt 实现数据驱动

    ddt 是第三方模块,需安装, pip install ddt DDT包含类的装饰器ddt和两个方法装饰器data(直接输入测试数据) 通常情况下,data中的数据按照一个参数传递给测试用例,如果da ...

  5. 2019-8-30-C#-从零开始写-SharpDx-应用-笔刷

    title author date CreateTime categories C# 从零开始写 SharpDx 应用 笔刷 lindexi 2019-8-30 8:50:0 +0800 2019-6 ...

  6. Leetcode788.Rotated Digits旋转数字

    我们称一个数 X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数.要求每位数字都要被旋转. 如果一个数的每位数字被旋转以后仍然还是一个数字, 则这个 ...

  7. 观察者模式(Java实现)

    import java.util.ArrayList; import java.util.Iterator; /* 抽象观察者类 */ abstract class Observer { public ...

  8. poj 2431 【优先队列】

    poj 2431 Description A group of cows grabbed a truck and ventured on an expedition deep into the jun ...

  9. Gym - 101962B_Color Changing Sofa

    题意:将一个沙发放到一个分成好几个色块(一个字母代表一种颜色)的房间里,要求沙发染成跟所在色块一样的颜色,沙发分成(0,1)两种,0可以染成一种颜色,1可以染成一种颜色(换句话说,沙发最多两种颜色), ...

  10. spider csdn博客和quantstart文章

    spider csdn博客和quantstart文章 功能 提取csdn博客文章 提取quantstart.com 博客文章, Micheal Hall-Moore 创办的网站 特色功能就是: 想把原 ...