题目大意:

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

题解:

这道题考试的时候没想出来

于是便爆炸

结果今天下午拿出昨天准备的题表准备做题的时候

题表里就有这题..

欲哭无泪啊有木有... ...


  • 说正经的

假设我们可以做到用并查集实现区间减法

那么很显然的做法就是维护前缀并查集然后做差

但是并查集并不满足区间减法.

但是我们可以考虑一下如果并查集满足区间减法,那我们会拿它做什么

我们对并查集做差实际上就是想使并查集\([1,R]\)退回到删除掉\([1,L-1]\)区间内的边的状态

这什么玩意 ?? 这也能搞 ???

上面的思路都是考虑一个区间内有多少边对这个答案造成了影响.

我们反过来考虑,考虑一下每条边会影响哪些答案

我们想象一下并查集维护的过程及其对答案的影响:

每次加入一条边,如果边的两端未连通,那么直接连接两点,那么对所有包括了这个点的区间都一定会使这个区间的答案-1.我们定义此影响的起始端点为0.

如果两条点已经连通,由于我们已经计算过之前连通这两个点的边对答案的贡献了(贡献一定由编号最小的边做出).所以我们知道这条边对答案造成影响当且仅当这个区间不包括编号最小的边且包括当前的边.所以定义此影响的起始端点为最小边的编号.

为了使下一次操作依然正确,我们将找到的编号最小的边删除,并将当前边加入.不难发现这样是正确的.

所以我们只要求出某个区间中影响答案的起始端点小于询问端点的边的数目即可。

至于后面的这个操作可以用可持久化线段树维护

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef long long ll;
  6. inline void read(int &x){
  7. x=0;char ch;bool flag = false;
  8. while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
  9. while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
  10. }
  11. const int maxn = 200010;
  12. const int inf = 0x3f3f3f3f;
  13. namespace lct{
  14. struct Node{
  15. Node *ch[2],*fa;
  16. int mn,w,tag;
  17. inline void update();
  18. inline void push_down();
  19. }*null;
  20. Node mem[maxn<<2],*it;
  21. inline void init(){
  22. it = mem;null = it++;
  23. null->ch[0] = null->ch[1] = null->fa = null;
  24. null->mn = null->w = inf;null->tag = 0;
  25. }
  26. inline Node* newNode(int val){
  27. Node *p = it++;p->w = p->mn = val;
  28. p->ch[0] = p->ch[1] = p->fa = null;
  29. p->tag = 0;return p;
  30. }
  31. inline void Node::update(){
  32. mn = min(min(ch[0]->mn,ch[1]->mn),w);
  33. }
  34. inline void Node::push_down(){
  35. if(this == null || tag == 0) return;
  36. if(ch[0] != null) ch[0]->tag ^= 1;
  37. if(ch[1] != null) ch[1]->tag ^= 1;
  38. swap(ch[0],ch[1]);tag = 0;
  39. }
  40. inline void rotate(Node *p,Node *x){
  41. int k = p == x->ch[1];
  42. Node *y = p->ch[k^1],*z = x->fa;
  43. if(z->ch[0] == x) z->ch[0] = p;
  44. if(z->ch[1] == x) z->ch[1] = p;
  45. if(y != null) y->fa = x;
  46. p->fa = z;p->ch[k^1] = x;
  47. x->fa = p;x->ch[k] = y;
  48. x->update();p->update();
  49. }
  50. inline bool isroot(Node *p){
  51. return (p == null) || (p->fa->ch[0] != p && p->fa->ch[1] != p);
  52. }
  53. inline void Splay(Node *p){
  54. p->push_down();
  55. while(!isroot(p)){
  56. Node *x = p->fa,*y = x->fa;
  57. y->push_down();x->push_down();p->push_down();
  58. if(isroot(x)) rotate(p,x);
  59. else if((x->ch[0] == p)^(y->ch[0] == x)) rotate(p,x),rotate(p,y);
  60. else rotate(x,y),rotate(p,x);
  61. }p->update();
  62. }
  63. inline Node* Access(Node *x){
  64. for(Node *y = null;x != null;y=x,x=x->fa)
  65. Splay(x),x->ch[1] = y,x->update();
  66. }
  67. inline void makeroot(Node *p){
  68. Access(p);Splay(p);p->tag ^= 1;
  69. }
  70. inline void link(Node *x,Node *y){
  71. makeroot(x);x->fa = y;
  72. }
  73. inline void cut(Node *x,Node *y){
  74. makeroot(x);Access(y);Splay(y);
  75. y->ch[0] = y->ch[0]->fa = null;
  76. y->update();
  77. }
  78. inline Node* findroot(Node *x){
  79. Access(x);Splay(x);
  80. while(x->ch[0] != null) x = x->ch[0];
  81. Splay(x);return x;
  82. }
  83. inline int query(Node *x,Node *y){
  84. makeroot(x);Access(y);Splay(y);
  85. return y->mn;
  86. }
  87. }
  88. namespace seg{
  89. struct Node{
  90. Node* ch[2];
  91. int num;
  92. void update();
  93. }*null;
  94. Node mem[maxn*30],*it;
  95. Node *root[maxn];
  96. inline void init(){
  97. it = mem;null = it++;
  98. null->ch[0] = null->ch[1] = null;
  99. null->num = 0;root[0] = null;
  100. }
  101. inline void Node::update(){
  102. num = ch[0]->num + ch[1]->num;
  103. }
  104. Node* insert(Node *rt,int l,int r,int pos){
  105. Node *p = it++;(*p) = (*rt);
  106. if(l == r){
  107. p->num ++;
  108. return p;
  109. }
  110. int mid = (l+r) >> 1;
  111. if(pos <= mid) p->ch[0] = insert(p->ch[0],l,mid,pos);
  112. else p->ch[1] = insert(p->ch[1],mid+1,r,pos);
  113. p->num = p->ch[0]->num + p->ch[1]->num;
  114. return p;
  115. }
  116. int query(Node *x,Node *y,int l,int r,int L,int R){
  117. if(L <= l && r <= R) return y->num - x->num;
  118. int mid = (l+r) >> 1;
  119. if(R <= mid) return query(x->ch[0],y->ch[0],l,mid,L,R);
  120. if(L > mid) return query(x->ch[1],y->ch[1],mid+1,r,L,R);
  121. return query(x->ch[0],y->ch[0],l,mid,L,R) + query(x->ch[1],y->ch[1],mid+1,r,L,R);
  122. }
  123. }
  124. lct::Node* mp[maxn];
  125. struct Node{
  126. int u,v;
  127. }e[maxn];
  128. int main(){
  129. lct::init();seg::init();
  130. int n,m,q,type;read(n);read(m);read(q);read(type);
  131. for(int i=1;i<=n;++i) lct::newNode(inf);
  132. for(int i=1;i<=m;++i){
  133. mp[i] = lct::newNode(i);
  134. read(e[i].u);read(e[i].v);
  135. if( lct::findroot(lct::mem+e[i].u) != lct::findroot(lct::mem+e[i].v)){
  136. lct::link(lct::mem+e[i].u,mp[i]);
  137. lct::link(lct::mem+e[i].v,mp[i]);
  138. seg::root[i] = seg::insert(seg::root[i-1],0,m,0);
  139. }else if(e[i].u == e[i].v){
  140. seg::root[i] = seg::insert(seg::root[i-1],0,m,m);
  141. }else{
  142. int x = lct::query(lct::mem+e[i].u,lct::mem+e[i].v);
  143. seg::root[i] = seg::insert(seg::root[i-1],0,m,x);
  144. lct::cut(mp[x],lct::mem+e[x].u);
  145. lct::cut(mp[x],lct::mem+e[x].v);
  146. lct::link(mp[i],lct::mem+e[i].u);
  147. lct::link(mp[i],lct::mem+e[i].v);
  148. }
  149. }
  150. int u,v,lastans = 0;
  151. while(q--){
  152. read(u);read(v);
  153. if(type) u ^= lastans,v ^= lastans;
  154. int x = seg::query(seg::root[u-1],seg::root[v],0,m,0,u-1);
  155. printf("%d\n",lastans = (n - x));
  156. }
  157. getchar();getchar();
  158. return 0;
  159. }

bzoj 3514: GERALD07加强版 lct+可持久化线段树的更多相关文章

  1. 【bzoj3514】Codechef MARCH14 GERALD07加强版 LCT+可持久化线段树

    题目描述 N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 输入 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密.接下来M行,代表图中的每条边 ...

  2. BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT+可持久化线段树

    自己独自想出来并切掉还是很开心的~ Code: #include <bits/stdc++.h> #define N 400005 #define inf 1000000000 #defi ...

  3. BZOJ 3514 GERALD07加强版 (LCT+主席树)

    题目大意:给定n个点m条边无向图,每次询问求当图中有编号为[L,R]的边时,整个图的联通块个数,强制在线 神题!(发现好久以前的题解没有写完诶) 我们要求图中联通块的个数,似乎不可搞啊. 联通块个数= ...

  4. [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)

    [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...

  5. bzoj 3673&3674 可持久化并查集&加强版(可持久化线段树+启发式合并)

    CCZ在2015年8月25日也就是初三暑假要结束的时候就已经能切这种题了%%% 学习了另一种启发式合并的方法,按秩合并,也就是按树的深度合并,实际上是和按树的大小一个道理,但是感觉(至少在这题上)更好 ...

  6. 【XSY2528】道路建设 LCT 可持久化线段树

    题目描述 给你一个\(n\)个点\(m\)条边图,\(q\)个询问,每次问你边权在\([l,r]\)之间的边组成的最小生成树(森林)的边权和.强制在线. \(n,m,q\leq 100000\) 题解 ...

  7. BZOJ.2653.[国家集训队]middle(可持久化线段树 二分)

    BZOJ 洛谷 求中位数除了\(sort\)还有什么方法?二分一个数\(x\),把\(<x\)的数全设成\(-1\),\(\geq x\)的数设成\(1\),判断序列和是否非负. 对于询问\(( ...

  8. BZOJ 3653: 谈笑风生(DFS序+可持久化线段树)

    首先嘛,还是太弱了,想了好久QAQ 然后,这道题么,明显就是求sigma(size[x]) (x是y的儿子且层树小于k) 然后就可以发现:把前n个节点按深度建可持久化线段树,就能用前缀和维护了 其实不 ...

  9. bzoj 4504: K个串 可持久化线段树+堆

    题目: Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一 个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计一次). 兔子们想 ...

随机推荐

  1. AFN多文件进度下载

    AFN参考资料 http://www.jianshu.com/p/c36159094e24 http://blog.cnbang.net/tech/2320/http://blog.cnbang.ne ...

  2. go语言之并发编程 channel

    前面介绍了goroutine的用法,如果有多个goroutine的话相互之间是如何传递数据和通信的呢.在C语言或者JAVA中,传输的方法包括共享内存,管道,信号.而在Go语言中,有了更方便的方法,就是 ...

  3. Oracle视图传递参数

    在Oracle里,视图不像存储过程和函数一样,可以定义输入参数,但我们可以变个方式,使用程序包来实现. oracle package: oracle package是oracle包,是一组相关过程.函 ...

  4. Bootstrap学习3--栅格系统

    备注:最新Bootstrap手册:http://www.jqhtml.com/bootstraps-syntaxhigh/index.html 目录1.简介2.栅格选项3.列偏移4.嵌套列5.列排序 ...

  5. shell基础part1

    shell基础一 一.什么是shell shell是个功能强大的编程语言,也是个解释执行的脚本语言(命令解释器). 二.shell分类 1.bourne shell (包括sh.ksh.Bash.ps ...

  6. iOS 屏幕原点坐标 && 导航栏风格的自定义

    其一 屏幕原点坐标 (x ,y) 受 self.navigationController. navigationBar 的 setTranslucent (BOOL) 属性控制 在 iOS7 以后   ...

  7. hadoop自带例子SecondarySort源码分析MapReduce原理

    这里分析MapReduce原理并没用WordCount,目前没用过hadoop也没接触过大数据,感觉,只是感觉,在项目中,如果真的用到了MapReduce那待排序的肯定会更加实用. 先贴上源码 pac ...

  8. ps 切片 蓝色 灰色 小标志 什么意思

    切片颜色 区分自动切片与用户切片和基于图层的切片.默认情况下,用户切片和基于图层的切片带蓝色标记,而自动切片带灰色标记.-----用户切片就是你需要的切片,其他区域会形成自动切片,可以视为自己不要的, ...

  9. SpringBoot2.0之整合RabbitMQ

    案例: Springboot 对RabbitMQ的支持 公共的pom: <project xmlns="http://maven.apache.org/POM/4.0.0" ...

  10. pathinfo()的用法

    pathinfo() 返回一个关联数组包含有 path 的信息. 包括以下的数组元素: [dirname] [basename] [extension] 提示和注释 注释:如果不是要求取得所有单元,则 ...