[la P5031&hdu P3726] Graph and Queries

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Problem Description
You are given an undirected graph with N vertexes and M edges. Every vertex in this graph has an integer value assigned to it at the beginning. You're also given a sequence of operations and you need to process them as requested. Here's a list of the possible operations that you might encounter:
1)  Deletes an edge from the graph.
The format is [D X], where X is an integer from 1 to M, indicating the ID of the edge that you should delete. It is guaranteed that no edge will be deleted more than once.
2)  Queries the weight of the vertex with K-th maximum value among all vertexes currently connected with vertex X (including X itself).
The format is [Q X K], where X is an integer from 1 to N, indicating the id of the vertex, and you may assume that K will always fit into a 32-bit signed integer. In case K is illegal, the value for that query will be considered as undefined, and you should return 0 as the answer to that query.
3)  Changes the weight of a vertex.
The format is [C X V], where X is an integer from 1 to N, and V is an integer within the range [-106, 106].

The operations end with one single character, E, which indicates that the current case has ended.
For simplicity, you only need to output one real number - the average answer of all queries.

Input
There are multiple test cases in the input file. Each case starts with two integers N and M (1 <= N <= 2 * 104, 0 <= M <= 6 * 104), the number of vertexes in the graph. The next N lines describes the initial weight of each vertex (-106 <= weight[i] <= 106). The next part of each test case describes the edges in the graph at the beginning. Vertexes are numbered from 1 to N. The last part of each test case describes the operations to be performed on the graph. It is guaranteed that the number of query operations [Q X K] in each case will be in the range [1, 2 * 105], and there will be no more than 2 * 105 operations that change the values of the vertexes [C X V].

There will be a blank line between two successive cases. A case with N = 0, M = 0 indicates the end of the input file and this case should not be processed by your program.

Output
For each test case, output one real number – the average answer of all queries, in the format as indicated in the sample output. Please note that the result is rounded to six decimal places.

Sample Input
3 3
10
20
30
1 2
2 3
1 3
D 3
Q 1 2
Q 2 1
D 2
Q 3 2
C 1 50
Q 1 1
E
3 3
10
20
20
1 2
2 3
1 3
Q 1 1
Q 1 2
Q 1 3
E
0 0

Sample Output
Case 1: 25.000000
Case 2: 16.666667

Hint

For the first sample: D 3 -- deletes the 3rd edge in the graph (the remaining edges are (1, 2) and (2, 3)) Q 1 2 -- finds the vertex with the second largest value among all vertexes connected with 1. The answer is 20. Q 2 1 -- finds the vertex with the largest value among all vertexes connected with 2. The answer is 30. D 2 -- deletes the 2nd edge in the graph (the only edge left after this operation is (1, 2)) Q 3 2 -- finds the vertex with the second largest value among all vertexes connected with 3. The answer is 0 (Undefined). C 1 50 -- changes the value of vertex 1 to 50. Q 1 1 -- finds the vertex with the largest value among all vertex connected with 1. The answer is 50. E -- This is the end of the current test case. Four queries have been evaluated, and the answer to this case is (20 + 30 + 0 + 50) / 4 = 25.000. For the second sample, caution about the vertex with same weight: Q 1 1 – the answer is 20 Q 1 2 – the answer is 20 Q 1 3 – the answer is 10.

 
Source

这题很经典,但又有坑——

首先,这题涉及到删边。

删边不方便,这时我们自然会想到删边的反面——加边。

那我们就可以倒着来操作,方便D操作。

但同时,每个点的权值也要从终状态到始状态来变化。

然后,我们就可以用并查集来实现加边操作,就把一条边加上了。

当然,最终状态也存在一些边,刚开始也要连上。

然后,Q操作要求我们查询连通块内第k大,如果k不合法则返回0。

第k大可以用一个平衡树来维护,我用了treap名次树,方便一些。

但是,注意这里的第k大可能有些定义上的模糊,我最后几发就被坑了。

似乎没有人是加了一个“相同点的个数”这个域A掉了的,我也是改用lrj的写法才A了的,这个需要注意一下。

然后第k大不合法,有可能是超出连通块大小,也有可能k<1。

对于C操作,就相当于再某个连通块中先删掉一个点权为w1的点,再加入一个点权为为w2的点,w1,w2就不多说了。

但是无论如何,都要注意,点权的变化顺序是怎样的。

如果就这样写——就T了。

为什么呢?可能会有数据卡“加边”这一个操作。在这里我们需要合并两颗平衡树。

怎么合并?我们采用启发式合并。就是从节点数小的向节点数大的树并。

怎么证明这样操作的时间复杂度是对的?假设树T1有n1个节点,T2有n2个节点,且n1>n2。

那么显然,我们会把T2并到T1里面。复杂度接近于O(n2logn1)。

由于对于原来T2里的每个点,它所在的树的大小至少增大了一倍,所以对于任意节点,它会被移动不超过logn次。

所以总复杂度是O(n(logn)^2)的。

然后。。通过这个题目,学到了treap的启发式合并和删除。。

code:

  1. %:pragma GCC optimize()
  2. #include<bits/stdc++.h>
  3. #define LL long long
  4. using namespace std;
  5. ,M=,Q=;
  6. int n,m,q,cas,w[N],fa[N];
  7. char ch; LL ans,cnt; bool vis[M];
  8. struct edg {int x,y;}a[M];
  9. struct opt {char t; int x,k;}o[Q];
  10. class node {
  11. private:
  12. public:
  13. ];
  14. node() {ch[]=ch[]=;}
  15. inline void newnode(node* &cu,int v) {
  16. cu=;
  17. }
  18. inline void update(node* &cu) {
  19. cu->s=;
  20. ]!=) cu->s+=cu->ch[]->s;
  21. ]!=) cu->s+=cu->ch[]->s;
  22. }
  23. inline void rotate(node* &cu,bool dr) {
  24. node* tmp=cu->ch[dr^]->ch[dr];
  25. cu->ch[dr^]->ch[dr]=cu;
  26. cu=cu->ch[dr^];
  27. cu->ch[dr]->ch[dr^]=tmp;
  28. update(cu->ch[dr]);
  29. update(cu);
  30. }
  31. inline void insert(node* &cu,int v) {
  32. ) {newnode(cu,v); return;}
  33. bool p=v<=cu->v;
  34. insert(cu->ch[p],v);
  35. );
  36. else update(cu);
  37. }
  38. inline void remove(node* &cu,int v) {
  39. ) return;
  40. if (v==cu->v) {
  41. ]==&&cu->ch[]==) {cu=; return;}
  42. ]==||cu->ch[]==) {
  43. cu=cu->ch[]==?cu->ch[]:cu->ch[]; return;
  44. }
  45. ]->k>cu->ch[]->k;
  46. rotate(cu,p^);
  47. remove(cu->ch[p^],v);
  48. update(cu);
  49. return;
  50. }
  51. int p=v<=cu->v;
  52. remove(cu->ch[p],v);
  53. update(cu);
  54. }
  55. inline int kth(node* cu,int k) {
  56. ||cu==) ;
  57. ]!=)?cu->ch[]->s:;
  58. ) return cu->v;
  59. ) ],k);
  60. ],k-s-);
  61. }
  62. inline void merge(node* &major,node* &minor) {
  63. insert(major,minor->v);
  64. ]!=) merge(major,minor->ch[]);
  65. ]!=) merge(major,minor->ch[]);
  66. ;
  67. }
  68. inline void clear(node* &cu) {
  69. ]!=) clear(cu->ch[]);
  70. ]!=) clear(cu->ch[]);
  71. ;
  72. }
  73. }t,*root[N];
  74. inline int read() {
  75. ,f=; ch=getchar();
  76. ') {if (ch=='-') f=-f; ch=getchar();}
  77. +ch-',ch=getchar();
  78. return x*f;
  79. }
  80. inline char readch() {
  81. while (ch<'A'||ch>'Z') ch=getchar();
  82. return ch;
  83. }
  84. inline int get(int x) {
  85. return fa[x]==x?x:fa[x]=get(fa[x]);
  86. }
  87. int main() {
  88. srand(),cas=;
  89. while (scanf("%d%d",&n,&m)!=EOF&&n) {
  90. ans=cnt=q=,memset(vis,,sizeof vis);
  91. ,x; i<=n; i++) w[i]=read();
  92. ; i<=m; i++) a[i].x=read(),a[i].y=read();
  93. for ( ; ; ) {
  94. o[++q].t=readch();
  95. if (o[q].t=='E') break;
  96. o[q].x=read();
  97. if (o[q].t!='D') o[q].k=read();
  98. }
  99. ,v; i<q; i++) {
  100. ;
  101. if (o[i].t=='C') swap(w[o[i].x],o[i].k);
  102. }
  103. ; i<=n; i++) {
  104. fa[i]=i; ) t.clear(root[i]);
  105. }
  106. ,x,y; i<=m; i++) if (!vis[i]) {
  107. x=get(a[i].x),y=get(a[i].y);
  108. if (x==y) continue; else fa[x]=y;
  109. }
  110. ; i<=n; i++) t.insert(root[get(i)],w[i]);
  111. ; i--) {
  112. if (o[i].t=='D') {
  113. x=get(a[o[i].x].x),y=get(a[o[i].x].y);
  114. if (x==y) continue;
  115. if (root[x]->s>root[y]->s) fa[y]=x,t.merge(root[x],root[y]);
  116. else fa[x]=y,t.merge(root[y],root[x]);
  117. }else
  118. if (o[i].t=='Q'){
  119. cnt++,ans+=(LL)t.kth(root[get(o[i].x)],o[i].k);
  120. }
  121. else
  122. if (o[i].t=='C') {
  123. t.remove(root[x=get(o[i].x)],w[o[i].x]);
  124. t.insert(root[x],o[i].k);
  125. w[o[i].x]=o[i].k;
  126. }
  127. }
  128. printf("Case %d: %.6lf\n",++cas,1.0*ans/cnt);
  129. }
  130. ;
  131. }

[la P5031&hdu P3726] Graph and Queries的更多相关文章

  1. HDU 3726 Graph and Queries treap树

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

  2. HDU 3726 Graph and Queries 平衡树+前向星+并查集+离线操作+逆向思维 数据结构大综合题

    Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  3. HDU 3726 Graph and Queries (离线处理+splay tree)

    Graph and Queries Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  4. HDU 3726 Graph and Queries(平衡二叉树)(2010 Asia Tianjin Regional Contest)

    Description You are given an undirected graph with N vertexes and M edges. Every vertex in this grap ...

  5. LA - 5031 - Graph and Queries

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

  6. LA 5031 Graph and Queries —— Treap名次树

    离线做法,逆序执行操作,那么原本的删除边的操作变为加入边的操作,用名次树维护每一个连通分量的名次,加边操作即是连通分量合并操作,每次将结点数小的子树向结点数大的子树合并,那么单次合并复杂度O(n1lo ...

  7. hdu 5412 CRB and Queries

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5412 CRB and Queries Description There are $N$ boys i ...

  8. HDU 4034 Graph(Floyd变形——逆向判断)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4034 Problem Description Everyone knows how to calcu ...

  9. HDU 5412 CRB and Queries(区间第K大 树套树 按值建树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=5412 Problem Description There are N boys in CodeLan ...

随机推荐

  1. VoiceXML标识元素及其属性

    VoiceXML 元素 <assign> 给变量赋值. <audio> 播放语音文件. <block> 无用户交互的可执行代码块. <catch> 捕获 ...

  2. 十、无事勿扰,有事通知(1)——NSNotification

    概述 很久很久以前,有一只菜鸟正在美滋滋的撸着他的嵌入式C代码.然而有一天,老板对菜鸟说:“别撸C了,从现在开始你就写swift开发ios了.”菜鸟一脸懵逼,但还是照做了. 又有一天,菜蛋谄媚的对菜鸟 ...

  3. 使用Typescript写的Vue初学者Hello World实例(实现按需加载、跨域调试、await/async)

    万事开头难,一个好的Hello World程序可以节省我们好多的学习时间,帮助我们快速入门.Hello World程序之所以是入门必读必会,就是因为其代码量少,简单易懂.但我觉得,还应该做到功能丰富, ...

  4. HBase笔记5(诊断)

    阻塞急救: RegionServer内存设置太小: 解决方案: 设置Region Server的内存要在conf/hbase-env.sh中添加export HBASE_REGIONSERVER_OP ...

  5. 如何为 SpringMVC 编写单元测试:普通 Controller 测试(转)

    前一篇文章我们已经知道如何配置使用了 SpringMVC 测试框架的单元测试. 现在我们就该亲身实践下如何为普通 Controller 编写单元测试了. 接下来一个很明显的问题就是: 什么是普通 Co ...

  6. [macOS] PHP双版本,5.6跟7.1

    转过来的,原文看这里,https://www.symfony.fi/page/how-to-run-both-php-5-6-and-php-7-x-with-homebrew-on-os-x-wit ...

  7. Numpy 数据类型和基本操作

    Numpy 数据类型 bool 用一位存储的布尔类型(值为TRUE或FALSE) inti 由所在平台决定其精度的整数(一般为int32或int64) int8 整数,范围为128至127 int1 ...

  8. docker基本管理

    一.docker基本命令 1.docker 获取镜像 将从 Docker Hub 仓库下载一个 Ubuntu 12.04 操作系统的镜像 docker pull ubuntu:12.04 Pullin ...

  9. Java连接数据库 #06# SQL与代码分离(精化版本)

    索引 DAO层依赖关系草图 应用示例 接Java连接数据库#05#,对代码进行改进. DAO层依赖关系草图 应用示例(只需3步!) 1.首先定义接口类: package org.sample.shop ...

  10. poj 3294 Life Forms - 后缀数组 - 二分答案

    题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...