离线做法,逆序执行操作,那么原本的删除边的操作变为加入边的操作,用名次树维护每一个连通分量的名次,加边操作即是连通分量合并操作,每次将结点数小的子树向结点数大的子树合并,那么单次合并复杂度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. ASP.NET Core 中使用TypeScript

    ASP.NET Core 注意:Visual Studio 2017和最新版本的ASP.NET的更新即将推出! 安装 ASP.NET Core 和 TypeScript 首先,若有必要请安装 ASP. ...

  2. 逐行粒度的vuex源码分析

    vuex源码分析 了解vuex 什么是vuex vuex是一个为vue进行统一状态管理的状态管理器,主要分为state, getters, mutations, actions几个部分,vue组件基于 ...

  3. windows10 中微信(UWP)版本不显示通知消息

    前言: 前段时间笔者更换了升级了WINDOWS10系统,从应用商店安装微信后,使用期间不会推送消息通知,右下角的通知栏也无法添加微信图标.搜索百度和Google后,发现很多人都是这样,这是微信(UWP ...

  4. 为什么要用Spring的依赖注入

    最近写了一些Spring项目,用到了依赖注入,但是不知道为甚么要用,后来在知乎上看了一些大家的回答,觉得很精辟,遂简单总结一下. 主要是实现类之间的解耦,假如A类依赖B类,在实例化A类的话也要new一 ...

  5. windows下 python中报错ImportError: No module named 'requests'

    原因没有安装requests模块, 可以切换到python的安装目录找到 script文件夹 example: 进入cmd窗口切换到上面的目录直接运营下面两个命令中的一个 1. > Path\p ...

  6. 【JZOJ3211】【SDOI2013】随机数生成器

    ╰( ̄▽ ̄)╭ 小 W喜欢读 书,尤其喜欢读 书,尤其喜欢读<约翰克里斯 朵夫>. 最近小 W准备读一本新书,这本一共有 p页, 页码范围为 0..p -1. 小 W很忙,所以每天只能读一 ...

  7. linux下播放器设计和开发

    http://blog.csdn.net/henryjee/article/details/6737392 本文根据DawnLightPlayer的开发经验写成.DawnLithtPlayer是今天3 ...

  8. poj2449第K短路问题(A*算法)

    启发函数:f(x)=g(x)+h(x); g(x)表示初始点到x状态的代价,h(x)表示从x的状态到目标状态的代价的估计值(并不是真实的),实际最小代价<=h(x); 起点s,终点t,x.v=s ...

  9. day39-Spring 05-Spring的AOP:不带有切点的切面

    Spring底层的代理的实现: 不带切点的切面是对类里面的所有的方法都进行拦截. 做Spring AOP的开发需要两个包:一个是AOP的包,一个是AOP联盟的包(因为规范是由AOP联盟提出来的). 用 ...

  10. JavaScript--天猫数量输入框

    <!DOCTYPE html> <head> <meta charset="utf-8" /> <title>无标题文档</t ...