题目链接:https://vjudge.net/contest/159527#problem/A

题意:(求一个 图 中的连通分量中的 第 k 大)

一张图,n 个点,m 条边,

有一些操作:

删除 ID 为 x 的边,(从 1 到 m);

询问 x 所在的连通分量 里面第 k 大的权值;

把结点 X 的权值 改成 V;

求:

所有的询问后,计算平均值;

每个连通分量都是一颗Treap树,加边操作,就是树的合并;

刘汝佳采用的是离线算法,我还是第一次听说,但是还是可以按照题意直接模拟的(我猜,但是很麻烦);因为在Treap中删边不同于删点;

什么是离线算法呢?

把操作顺序反过来处理,执行完所有 删除边操作,然后建Treap,要是不在同一个连通分量里面(并查集判断),这就涉及到递归合并Treap树了,这里采用了启发式合并;

然后反向操作,遇到 D,就是加边(加边操作同上),

询问,就是在 X 所在连通分量里面,寻找第 k 大;

改权,就是删除这个点,然后从新加点;

  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. struct Node
  6. {
  7. Node *ch[];
  8. int r; //优先级
  9. int v; //值
  10. int s; //结点总数
  11.  
  12. Node(int v):v(v)
  13. {
  14. ch[] = ch[] = NULL;
  15. r = rand();
  16. s = ;
  17. }
  18.  
  19. bool operator < (const Node& rhs) const
  20. {
  21. return r < rhs.r;
  22. }
  23.  
  24. int cmp(int x) const
  25. {
  26. if(x==v) return -;
  27. return x < v ? : ;
  28. }
  29.  
  30. void maintain()
  31. {
  32. s = ;
  33. if(ch[]!=NULL) s+=ch[]->s;
  34. if(ch[]!=NULL) s+=ch[]->s;
  35. }
  36.  
  37. };
  38.  
  39. void rotate(Node* &o,int d)
  40. {
  41. Node* k = o->ch[d^];
  42. o->ch[d^] = k ->ch[d];
  43. k->ch[d] = o;
  44. o->maintain();
  45. k->maintain();
  46. o = k;
  47. }
  48.  
  49. void insert(Node* &o,int x)
  50. {
  51. if(o==NULL) o = new Node(x);
  52. else
  53. {
  54. int d = (x < o->v? : );
  55. insert(o->ch[d],x);
  56. if(o->ch[d]->r > o->r)
  57. rotate(o,d^);
  58. }
  59. o->maintain();
  60. }
  61.  
  62. void remove(Node* &o,int x)
  63. {
  64. int d = o->cmp(x);
  65. if(d==-)
  66. {
  67. Node* u = ;
  68. if(o->ch[]!=NULL&&o->ch[]!=NULL)
  69. {
  70. int d2 = (o->ch[]->r > o->ch[]->r ? : );
  71. rotate(o,d2);
  72. remove(o->ch[d2],x);
  73. }
  74. else
  75. {
  76. if(o->ch[]==NULL)
  77. o = o->ch[];
  78. else o = o->ch[];
  79. }
  80. }
  81. else
  82. remove(o->ch[d],x);
  83.  
  84. if(o!=NULL) o->maintain();
  85. }
  86.  
  87. const int maxc = + ;
  88. struct Command
  89. {
  90. char type;
  91. int x,p;
  92. } commands[maxc];
  93.  
  94. const int maxn = + ;
  95. const int maxm = + ;
  96. int n,m;
  97. int weight[maxn],from[maxm],to[maxm],removed[maxm];
  98.  
  99. int pa[maxn];
  100. int findset(int x)
  101. {
  102. return pa[x]!=x ? pa[x] = findset(pa[x]):x;
  103. }
  104.  
  105. Node* root[maxn]; //Treap
  106.  
  107. int kth(Node* o,int k)
  108. {
  109. if(o==NULL||k<=||k> o->s) return ;
  110. int s = (o->ch[]==NULL?:o->ch[]->s);
  111. if(k==s+) return o->v;
  112. else if(k<=s) return kth(o->ch[],k);
  113. else return kth(o->ch[],k-s-);
  114. }
  115.  
  116. void mergeto(Node* &src,Node* &dest)
  117. {
  118. if(src->ch[]!=NULL) mergeto(src->ch[],dest);
  119. if(src->ch[]!=NULL) mergeto(src->ch[],dest);
  120. insert(dest,src->v);
  121. delete src;
  122. src = NULL;
  123. }
  124.  
  125. void removetree(Node* &x)
  126. {
  127. if(x->ch[]!=NULL) removetree(x->ch[]);
  128. if(x->ch[]!=NULL) removetree(x->ch[]);
  129. delete x;
  130. x = NULL;
  131. }
  132.  
  133. void add_edge(int x)
  134. {
  135. int u = findset(from[x]),v=findset(to[x]);
  136. if(u!=v)
  137. {
  138. if(root[u]->s < root[v]->s)
  139. {
  140. pa[u] = v;
  141. mergeto(root[u],root[v]);
  142. }
  143. else
  144. {
  145. pa[v] = u;
  146. mergeto(root[v],root[u]);
  147. }
  148. }
  149. }
  150.  
  151. int query_cnt;
  152. long long query_tot;
  153. void query(int x,int k)
  154. {
  155. query_cnt++;
  156. query_tot +=kth(root[findset(x)],k);
  157. }
  158.  
  159. void change_weight(int x,int v)
  160. {
  161. int u = findset(x);
  162. remove(root[u],weight[x]);
  163. insert(root[u],v);
  164. weight[x] = v;
  165. }
  166.  
  167. int main()
  168. {
  169. int kase = ;
  170. while(scanf("%d%d",&n,&m)==&&n)
  171. {
  172. for(int i=; i<=n; i++)
  173. scanf("%d",&weight[i]);
  174. for(int i=; i<=m; i++)
  175. scanf("%d%d",&from[i],&to[i]);
  176. memset(removed,,sizeof(removed));
  177.  
  178. int c = ;
  179. for(;;)
  180. {
  181. char type;
  182. int x,p=,v = ;
  183. scanf(" %c",&type);
  184. if(type=='E') break;
  185. scanf("%d",&x);
  186. if(type=='D') removed[x]= ; //删掉的边
  187. if(type=='Q') scanf("%d",&p);
  188. if(type=='C')
  189. {
  190. scanf("%d",&v);
  191. p = weight[x];
  192. weight[x] = v;
  193. }
  194. commands[c++] = (Command)
  195. {
  196. type,x,p
  197. };
  198. }
  199.  
  200. //最终的图
  201. for(int i=; i<=n; i++)
  202. {
  203. pa[i] = i;
  204. if(root[i]!=NULL) removetree(root[i]);
  205. root[i] = new Node(weight[i]);
  206. }
  207. for(int i=; i<=m; i++)
  208. {
  209. if(!removed[i]) //id为i这条边没有被删掉
  210. add_edge(i);
  211. }
  212.  
  213. query_cnt = query_tot = ;
  214. for(int i=c-; i>=; i--)
  215. {
  216. if(commands[i].type=='D') add_edge(commands[i].x); //加上边
  217. if(commands[i].type=='Q') query(commands[i].x,commands[i].p);//第p大
  218. if(commands[i].type=='C') change_weight(commands[i].x,commands[i].p);
  219. }
  220.  
  221. printf("Case %d: %.6lf\n",++kase,query_tot/(double)query_cnt);
  222.  
  223. }
  224.  
  225. return ;
  226. }

LA 5031 图询问的更多相关文章

  1. LA - 5031 - Graph and Queries

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

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

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

  3. 使用vsphere client 克隆虚拟机

    免费的VMWare ESXi5.0非常强大,于是在vSphere5.0平台中ESXi取代了ESX.,使用ESXi经常会遇到这样的问题,我需要建立多个虚拟机,都是windows2003操作系统,难道必须 ...

  4. [BZOJ 1295][SCOI2009]最长距离(SPFA+暴力)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1295 分析:很巧妙的一道spfa从搜索的角度是搜索在所有1中搜索删除哪T个1,对整个图询问,这 ...

  5. poj1236 强连通

    题意:有 n 个学校每个学校可以将自己的软件共享给其他一些学校,首先,询问至少将软件派发给多少学校能够使软件传播到所有学校,其次,询问添加多少学校共享关系可以使所有学校的软件能够相互传达. 首先,第一 ...

  6. 虚拟化之vmware-vsphere (web) client

    两种客户端 vsphere client 配置>软件>高级设置里的变量 uservars.supressshellwarning=1 vsphere web client 安装完vSphe ...

  7. 如何使用vsphere client 克隆虚拟机

    vSphere 是VMware公司推出一套服务器虚拟化解决方案. 工具/原料 vSphere 测试系统 方法/步骤 1.进入vSphere client,关闭需要克隆的虚拟机win7 2.选中ESXi ...

  8. 【离线 撤销并查集 线段树分治】bzoj1018: [SHOI2008]堵塞的交通traffic

    本题可化成更一般的问题:离线动态图询问连通性 当然可以利用它的特殊性质,采用在线线段树维护一些标记的方法 Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常 ...

  9. vSphere Client克隆虚拟机

    免费的VMWare ESXi5.5非常强大,使用ESXi经常会遇到这样的问题,我需要建立多个虚拟机,系统一个一个安装很麻烦.VMware ESXi.VMware vCenter Server 和 vS ...

随机推荐

  1. iPhone10.3.X越狱后SSH连接不上的问题(已解决)

    iPhone10.3.X越狱后SSH连接不上的问题 G0blin RC2,iPhone5s10.3.3  Jailbreak 最近研究了好几天,试了好多的方法. ssh 访问越狱iPhone的两种方式 ...

  2. 技巧:Python中print打印信息的同时打印文件、行号

    import sys def Log(msg): print('Print Message: '+msg+' ,File: "'+__file__+'", Line '+str(s ...

  3. Problem02 输出素数

    题目:判断101-200之间有多少个素数,并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数. public class ...

  4. Sublime text中文乱码解决办法

    ConvertToUTF8 安装这个插件可以解决编码混乱问题 首先必须先配一下Sublime text ,安装 Package Control 1.  用Sublimt text 打开任意一个文件,C ...

  5. jquery 写ajax

    function down(t){ $.ajax({  url : 'selectWordDate',  data : {   date_time : t  },  dataType : 'json' ...

  6. FIR IIR数字滤波器特点简介

    FIR:有限脉冲滤波器,线性较好,用非递归算法,可用FFT,计算速度快,不用四舍五入,适合于对相位敏感的线性应用场合,设计灵活没有现成公式可用. 输出与现在和过去的输入有关. IIR:无限脉冲滤波器, ...

  7. Murano Weekly Meeting 2016.06.28

    Meeting time: 2016.June.28 1:00~2:00 Chairperson:  Kirill Zaitsev, from Mirantis Meeting summary: 1. ...

  8. Ubuntu 16.04下安装Charles抓包工具

    Charles是一个跨平台的抓包工具,虽然没有Fiddler做的这么完美,但是也算是另一个选择. 下载: https://www.charlesproxy.com/download/ 注册: http ...

  9. 左侧栏与右侧内容之锚点、offsetHeight、scrollTop()

    常用功能 1.点击左侧,右侧相关内容随时点到. 2.滚动右侧信息,左侧标题随之显示背景. 第一点很简单,只要在左侧栏  <li><a  href="#aaa"&g ...

  10. python面试题——前端(23题)

    2.谈谈你对websocket协议的认识. 3.什么是magic string ? 4.如何创建响应式布局? 5.你曾经使用过哪些前端框架? 6.什么是ajax请求?并使用jQuery和XMLHttp ...