题目链接

题意

给一个\(2\)x\(n\)的矩阵,每个格子看成一个点,每个格子与相邻的格子间有边。现进行一些加边与删边操作,问每次操作后图中有多少条割边。

思路

参考

https://www.cnblogs.com/rpSebastian/p/7834027.html

割边

在这个图中什么样的边才会是割边?情况貌似有点多。

那么满足什么条件的边不会是割边?在环里面的边。

的要求是什么?第一排和第二排对应位置都有边。

环里面哪些边不是割边?找到这个环中最左边和最右边的竖边,夹起来的一整块里面所有的横边和竖边都不是割边。

环外面可能有边不是割边吗?不可能。// 画一画图就知道了

线段树

由上面的讨论我们看到,对于一个环,要知道里面的非割边数目,就要知道这一块中

  1. 最左边和最右边的竖边;
  2. 里面的竖边的数目。

于是可以用线段树维护竖边的信息。

set

那每个环怎么记录呢?

用一个\(set\)记录上下都有边的一段段连续的边。

用\(cnt[i]\)数组记录\([i,i+1]\)一段的出现次数,取值只会是\(0\)或\(1\)或\(2\);当从\(1\)变成\(2\)或者从\(2\)变成\(1\)时更新\(set\)里维护的横边的信息,拆分或者合并。

注意

  1. 每次操作输出答案,并不需要每次都遍历一遍\(set\)去对每个环统计一次答案,而只要在每次操作的时候同时计算这个操作的影响即可。
  2. 因为比较函数是根据左端点排序,所以如果当前要插入的段与set里已有的段左端点相同(之前的尚未删除),就不会被插入;因此要用multiset.

Code

  1. #include <bits/stdc++.h>
  2. #define maxn 200010
  3. #define lson (rt<<1)
  4. #define rson (rt<<1|1)
  5. using namespace std;
  6. typedef long long LL;
  7. struct Tree { int l, r, lp, rp, cnt; }tr[maxn<<2];
  8. int num[maxn], ans;
  9. void build(int rt, int l, int r) {
  10. tr[rt].l = l, tr[rt].r = r; tr[rt].lp = l, tr[rt].rp = r, tr[rt].cnt = r-l+1;
  11. if (l == r) return;
  12. int mid = l+r >> 1;
  13. build(lson, l, mid), build(rson, mid+1, r);
  14. }
  15. void push_up(int rt) {
  16. tr[rt].cnt = tr[lson].cnt + tr[rson].cnt;
  17. tr[rt].lp = min(tr[lson].lp, tr[rson].lp);
  18. tr[rt].rp = max(tr[lson].rp, tr[rson].rp);
  19. }
  20. void modify(int rt, int p, int add) {
  21. if (tr[rt].l == tr[rt].r) {
  22. if (add) tr[rt].lp = tr[rt].rp = tr[rt].l, tr[rt].cnt = 1;
  23. else tr[rt].lp = maxn, tr[rt].rp = 0, tr[rt].cnt = 0;
  24. return;
  25. }
  26. int mid = tr[rt].l + tr[rt].r >> 1;
  27. if (p <= mid) modify(lson, p, add);
  28. else modify(rson, p, add);
  29. push_up(rt);
  30. }
  31. struct node2 { int l, r, cnt; };
  32. node2 ask(int rt, int l, int r) {
  33. if (tr[rt].l == l && tr[rt].r == r) {
  34. return {tr[rt].lp, tr[rt].rp, tr[rt].cnt};
  35. }
  36. int mid = tr[rt].l + tr[rt].r >> 1;
  37. if (r <= mid) return ask(lson, l, r);
  38. else if (l > mid) return ask(rson, l, r);
  39. else {
  40. node2 nl = ask(lson, l, mid), nr = ask(rson, mid+1, r);
  41. return {min(nl.l, nr.l), max(nl.r, nr.r), nl.cnt+nr.cnt};
  42. }
  43. }
  44. int ask(int l, int r) {
  45. node2 nd = ask(1, l, r);
  46. if (nd.l >= nd.r) return 0;
  47. return ((nd.r - nd.l) << 1) + nd.cnt;
  48. }
  49. struct node {
  50. int l, r;
  51. bool operator < (const node& nd) const { return l < nd.l; }
  52. };
  53. multiset<node> st;
  54. void del(int x) {
  55. --num[x];
  56. if (num[x]==0) return;
  57. auto p = st.upper_bound({x,x+1}); --p;
  58. ans += ask(p->l, p->r);
  59. if (p->l != x) ans -= ask(p->l, x), st.insert({p->l, x});
  60. if (p->r != x+1) ans -= ask(x+1, p->r), st.insert({x+1, p->r});
  61. st.erase(p);
  62. }
  63. void add(int x) {
  64. ++num[x];
  65. if (num[x]==1) return;
  66. auto pl = st.upper_bound({x,x+1}), pr = st.lower_bound({x,x+1}); --pl;
  67. if (pl->r==x && pr->l==x+1) {
  68. ans += ask(pl->l, pl->r);
  69. ans += ask(pr->l, pr->r);
  70. ans -= ask(pl->l, pr->r);
  71. st.insert({pl->l, pr->r});
  72. st.erase(pl), st.erase(pr);
  73. }
  74. else if (pl->r==x && pr->l!=x+1) {
  75. ans += ask(pl->l, pl->r);
  76. ans -= ask(pl->l, x+1);
  77. st.insert({pl->l, x+1});
  78. st.erase(pl);
  79. }
  80. else if (pl->r!=x && pr->l==x+1) {
  81. ans += ask(pr->l, pr->r);
  82. ans -= ask(x, pr->r);
  83. st.insert({x, pr->r}), st.erase(pr);
  84. }
  85. else {
  86. ans -= ask(x, x+1);
  87. st.insert({x,x+1});
  88. }
  89. }
  90. void work() {
  91. int n, m;
  92. scanf("%d%d", &n, &m);
  93. ans = 0;
  94. build(1, 1, n);
  95. st.clear();
  96. st.insert({1,n});
  97. st.insert({-1,-1});
  98. st.insert({n+2, n+2});
  99. for (int i = 1; i < n; ++i) num[i] = 2;
  100. while (m--) {
  101. int id,x1,y1,x2,y2;
  102. scanf("%d%d%d%d%d", &id, &x1, &y1, &x2, &y2);
  103. if (id==1) ++ans; else --ans;
  104. if (y1==y2) {
  105. auto p = st.upper_bound({y1,y1+1}); --p;
  106. bool flag = false;
  107. if (p->l<=y1 && p->r>=y1) flag = true;
  108. if (flag) ans += ask(p->l, p->r);
  109. if (id==1) modify(1, y1, 1);
  110. else modify(1, y1, 0);
  111. if (flag) ans -= ask(p->l, p->r);
  112. }
  113. else {
  114. if (id==2) del(min(y1,y2));
  115. else add(min(y1,y2));
  116. }
  117. printf("%d\n", ans);
  118. }
  119. }
  120. int main() {
  121. int T;
  122. scanf("%d", &T);
  123. while (T--) work();
  124. return 0;
  125. }

hdu 6218 Bridge 线段树 set的更多相关文章

  1. hdu 4031 attack 线段树区间更新

    Attack Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Subm ...

  2. hdu 4288 离线线段树+间隔求和

    Coder Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  3. hdu 3016 dp+线段树

    Man Down Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  4. HDU 5877 dfs+ 线段树(或+树状树组)

    1.HDU 5877  Weak Pair 2.总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个 3.思路:利用dfs遍历子节点,同时对于每个子节点au, ...

  5. HDU 3308 LCIS (线段树区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 题目很好懂,就是单点更新,然后求区间的最长上升子序列. 线段树区间合并问题,注意合并的条件是a[ ...

  6. HDU 2795 Billboard (线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题目大意:有一块h*w的矩形广告板,要往上面贴广告;   然后给n个1*wi的广告,要求把广告贴 ...

  7. hdu 5480 Conturbatio 线段树 单点更新,区间查询最小值

    Conturbatio Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=54 ...

  8. hdu 1828 Picture(线段树 || 普通hash标记)

    http://acm.hdu.edu.cn/showproblem.php?pid=1828 Picture Time Limit: 6000/2000 MS (Java/Others)    Mem ...

  9. hdu 4747【线段树-成段更新】.cpp

    题意: 给出一个有n个数的数列,并定义mex(l, r)表示数列中第l个元素到第r个元素中第一个没有出现的最小非负整数. 求出这个数列中所有mex的值. 思路: 可以看出对于一个数列,mex(r, r ...

随机推荐

  1. JavaScript算数

    常数                              Math.E 圆周率                           Math.PI 2的平方根                  ...

  2. java一些问题的解答

    1.java 枚举类型和数据二进制等问题思考 以下代码的输出结果是什么?为什么会有这样的输出结果? int X=100; int Y=200; System.out.println("X+Y ...

  3. Dialogue between Jack and Rose【jack 和 Rose的对话】

    Dialogue between Jack and Rose Rose : It's getting quiet. 越来越安静了 Jack : It's gonna take a couple of ...

  4. BFS:HDU2612-Find a way(双向BFS)

    Find a way Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  5. 阿里云服务器+Tomcat项目+mysql 发布项目全过程

    这个博客管理系统折腾我好几天了. 总结一下整个过程吧! 1.首先这个博客在tomcat下 windows系统可以完全跑起来了,无论是前台或者后台都能实现所有的功能. 2.然后我买了一个域名jasonj ...

  6. ActiveMQ初步学习

    本文主要参考张丰哲大神的简书文章,链接 https://www.jianshu.com/p/ecdc6eab554c JMS,即Java Message Service,通过面向消息中间件(MOM:M ...

  7. 【Clone Graph】cpp

    题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...

  8. Windows网络编程笔记4 -- Winsock 协议相关知识

     Win32平台上的Winsock编程,Winsock是一个与协议无关的接口.以下协议是我们需要了解的: 网络协议的特征包括: 1.  面向消息 2.  面向连接和无线接 3.  可靠性和次序性 4. ...

  9. 移动web前端开发小结

    注意:Chrome模拟手机的显示的界面是有误差的,强烈建议一定要在真机测试自己的移动端页面(以移动端页面为准). 1.页面高度渲染错误,页面的高度是否包含了导航,(华为手机就是偏偏有底部菜单) 设置窗 ...

  10. Selenium中如何运行 auto.exe 文件

    Runtime exe = Runtime.getRuntime(); try{ String str = "D:\\Auto上传文件\\photo.exe"; exe.exec( ...