1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #define maxn 400005
  7. #define maxm 200005
  8. #define maxk 4000005
  9. using namespace std;
  10.  
  11. int n,m,k,type,ans,Ans,size,fa[maxn],son[maxn][],sm[maxn],Val[maxm],val[maxn],sum[maxk],root[maxm],lc[maxk],rc[maxk];
  12. bool rev[maxn];
  13. struct date{
  14. int u,v;
  15. }wi[maxm];
  16.  
  17. struct note{
  18. bool which(int x){
  19. return son[fa[x]][]==x;
  20. }
  21. bool isroot(int x){
  22. return son[fa[x]][]!=x&&son[fa[x]][]!=x;
  23. }
  24. void update(int x){
  25. sm[x]=val[x];
  26. if (son[x][]) sm[x]=min(sm[x],sm[son[x][]]);
  27. if (son[x][]) sm[x]=min(sm[x],sm[son[x][]]);
  28. }
  29. void pushdown(int x){
  30. if (!rev[x]) return;
  31. rev[x]^=,swap(son[x][],son[x][]);
  32. if (son[x][]) rev[son[x][]]^=;
  33. if (son[x][]) rev[son[x][]]^=;
  34. }
  35. void relax(int x){
  36. if (!isroot(x)) relax(fa[x]);
  37. pushdown(x);
  38. }
  39. void rotata(int x){
  40. int y=fa[x],d=which(x),dd=which(y);
  41. if (!isroot(y)) son[fa[y]][dd]=x; fa[x]=fa[y];
  42. fa[son[x][d^]]=y,son[y][d]=son[x][d^];
  43. fa[y]=x,son[x][d^]=y;
  44. update(y);
  45. }
  46. void splay(int x){
  47. relax(x);
  48. while (!isroot(x)){
  49. if (isroot(fa[x])) rotata(x);
  50. else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
  51. else rotata(x),rotata(x);
  52. }
  53. update(x);
  54. }
  55. void access(int x){
  56. for (int p=;x;x=fa[x]){
  57. splay(x);
  58. son[x][]=p;
  59. p=x;
  60. update(x);
  61. }
  62. }
  63. void make_root(int x){
  64. access(x);
  65. splay(x);
  66. rev[x]^=;
  67. }
  68. void link(int x,int y){
  69. make_root(x);
  70. fa[x]=y;
  71. }
  72. void cut(int x,int y){
  73. make_root(x);
  74. access(y);
  75. splay(y);
  76. son[y][]=fa[x]=;
  77. update(y);
  78. }
  79. void split(int x,int y){
  80. make_root(x);
  81. access(y);
  82. splay(y);
  83. }
  84. int find_root(int x){
  85. access(x);
  86. splay(x);
  87. while (son[x][]) x=son[x][];
  88. return x;
  89. }
  90. int find(int x,int y){
  91. split(x,y);
  92. return sm[y];
  93. }
  94. }lct;
  95.  
  96. void insert(int &k,int p,int l,int r,int x){
  97. k=++size,sum[k]=sum[p]+;
  98. int mid=(l+r)/;
  99. if (l==r) return;
  100. if (x<=mid) rc[k]=rc[p],insert(lc[k],lc[p],l,mid,x);
  101. else lc[k]=lc[p],insert(rc[k],rc[p],mid+,r,x);
  102. }
  103.  
  104. void insert(int id,int x){
  105. insert(root[id],root[id-],,m+,x);
  106. }
  107.  
  108. void Query(int k1,int k2,int l,int r,int x,int y){
  109. if (!k1&&!k2) return;
  110. if (l>=x&&r<=y){
  111. Ans+=(sum[k2]-sum[k1]);
  112. return;
  113. }
  114. int mid=(l+r)/;
  115. if (x<=mid) Query(lc[k1],lc[k2],l,mid,x,y);
  116. if (y>mid) Query(rc[k1],rc[k2],mid+,r,x,y);
  117. }
  118.  
  119. int query(int x,int y){
  120. Ans=;
  121. int u=root[x-],v=root[y],l=,r=m+,mid;
  122. Query(u,v,l,r,,x-);
  123. return Ans;
  124. }
  125.  
  126. int main(){
  127. int u,v,t1,t2,temp;
  128. scanf("%d%d%d%d",&n,&m,&k,&type);
  129. memset(sum,,sizeof(sum));
  130. memset(Val,,sizeof(Val));
  131. memset(fa,,sizeof(fa));
  132. memset(son,,sizeof(son));
  133. memset(rev,,sizeof(rev));
  134. for (int i=;i<=m;i++) scanf("%d%d",&wi[i].u,&wi[i].v);
  135. for (int i=;i<=n;i++) val[i]=sm[i]=m+;
  136. for (int i=;i<=m;i++) val[n+i]=sm[n+i]=i;
  137. for (int i=;i<=m;i++){
  138. u=wi[i].u,v=wi[i].v;
  139. if (u==v) Val[i]=m+;
  140. if (u==v) continue;
  141. if (lct.find_root(u)!=lct.find_root(v)){
  142. Val[i]=;
  143. lct.link(n+i,u),lct.link(n+i,v);
  144. }else{
  145. temp=lct.find(u,v);
  146. Val[i]=temp,temp+=n;
  147. lct.cut(temp,wi[temp-n].u),lct.cut(temp,wi[temp-n].v);
  148. lct.link(n+i,u),lct.link(n+i,v);
  149. }
  150. }
  151. memset(root,,sizeof(root));
  152. for (int i=;i<=m;i++){
  153. insert(i,Val[i]);
  154. }
  155. ans=;
  156. for (int i=;i<=k;i++){
  157. scanf("%d%d",&u,&v);
  158. if (type==) u^=ans,v^=ans;
  159. if (u>v) swap(u,v);
  160. ans=n-query(u,v);
  161. printf("%d\n",ans);
  162. }
  163. return ;
  164. }

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3514

题目大意:N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

做法:如果要求整个图中联通块的个数,记加入该边后不形成环的边数记为x,则答案为n-x,这题问的是加入编号为[l~r]中的边后联通块的个数,答案便稍微变化了一下,记能使联通块数目-1的边集为{S},答案为n-|S|,问题便成为了:有多少条边属于{S},仔细想想,可以先预处理一个数组val[i],怎么预处理呢?可以按编号依次加入边,有两种情况:*1.如果加入的这条边不形成环,则这条边的权值赋值为0,并加入这条边;*2.加入这条边形成环,记环上编号最小的边的编号为y,这加入的这条边权值为y,并删去编号最小的那条边,加入该边。这个过程用lct模拟即可,比较基础的操作。

得出每条边的权值val[i]后,对于一个询问[L~R],如果一条边的val<l,则该边属于{S},问题便简化为一个数组val,问在区间L~R中权值在0~L-1的个数,显而易见,可持久化线段树轻松搞定。问题得以圆满解决。(Lct+可持久化线段树)

bzoj3514Codechef MARCH14 GERALD07加强版的更多相关文章

  1. 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1288  Solved: 490 ...

  2. BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )

    从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献 ...

  3. 【LCT+主席树】BZOJ3514 Codechef MARCH14 GERALD07加强版

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2023  Solved: 778 ...

  4. BZOJ 3514: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1312  Solved: 501 ...

  5. BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT

    BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. I ...

  6. [BZOJ 3514]Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES)

    [BZOJ3514] Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES) 题意 \(N\) 个点 \(M\) 条边的无向图,\(K\) 次询问保 ...

  7. [BZOJ3514]CodeChef MARCH14 GERALD07加强版(LCT+主席树)

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2177  Solved: 834 ...

  8. bzoj3514 Codechef MARCH14 GERALD07加强版 lct预处理+主席树

    Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1951  Solved: 746[Submi ...

  9. BZOJ3514 : Codechef MARCH14 GERALD07加强版

    以边编号为权值 用Link-cut Tree维护最大生成树 对于新加的第i条边(u,v) a[i]表示当a[i]这条边加入后连通块个数会减少 若u==v则a[i]=m 若u与v不连通则连上,a[i]= ...

随机推荐

  1. 准备NOIP2017 最长公共子序列(模版)

    一些概念: (1)子序列: 一个序列A = a1,a2,--an,中任意删除若干项,剩余的序列叫做A的一个子序列.也可以认为是从序列A按原顺序保留任意若干项得到的序列.例如:   对序列 1,3,5, ...

  2. BZOJ 1030 【JSOI2007】 文本生成器

    Description JSOI交给队员ZYX一个任务,编制一个称之为"文本生成器"的电脑软件:该软件的使用者是一些低幼人群,他们现在使用的是GW文本生成器v6版.该软件可以随机生 ...

  3. LeetCode 01 Two Sum swift

    class TwoSum { func sumTow(nums: [Int], target: Int)->[Int]{ ,]; ;x<nums.count;x++){ ;y<num ...

  4. 【转】$_POST 与 php://input的区别分析

    $data = file_get_contents("php://input"); php://input 是个可以访问请求的原始数据的只读流. POST 请求的情况下,最好使用 ...

  5. noi题库(noi.openjudge.cn) 1.5编程基础之循环控制T36——T45

    T36 计算多项式的值 描述 假定多项式的形式为xn+xn-1+-+x2+x+1,请计算给定单精度浮点数x和正整数n值的情况下这个多项式的值. 输入 输入仅一行,包括x和n,用单个空格隔开.x在flo ...

  6. string to char* and char* to string 玩转 String 和 Char*

    char 类型是c语言中常见的一个数据类型,string是c++中的一个,它的定义为 Strings are objects that represent sequences of character ...

  7. WPF 3D模型 3D场景

    1.首先得说明的是这并不是真正的3D,模型被导出为一系列的单个图片,例如一个3D户型图,以某个视角旋转360°,渲染出一系列连续的单个图片文件. 2.在Image.MouseMove事件中添加相应代码 ...

  8. 理解AngularJS生命周期:利用ng-repeat动态解析自定义directive

    ng-repeat是AngularJS中一个非常重要和有意思的directive,常见的用法之一是将某种自定义directive和ng-repeat一起使用,循环地来渲染开发者所需要的组件.比如现在有 ...

  9. CI(CodeIgniter)框架入门教程——第二课 初始MVC

    本文转载自:http://www.softeng.cn/?p=53 今天的主要内容是,使用CodeIgniter框架完整的MVC内容来做一个简单的计算器,通过这个计算器,让大家能够体会到我在第一节课中 ...

  10. Realm Java的学习、应用、总结

    从React Native珠三角沙龙会议了解到Realm这个开源库,然后开始学习.理解和使用Realm.Realm是跨平台.支持多种主流语言,这里主要是对Realm Java结合实际项目的一些情况进行 ...