Description

During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.

Frequently the invaders launched attack on some of the villages and
destroyed the parts of tunnels in them. The Eighth Route Army
commanders requested the latest connection state of the tunnels and
villages. If some villages are severely isolated, restoration of
connection must be done immediately!

Input

The
first line of the input contains two positive integers n and m (n, m ≤
50,000) indicating the number of villages and events. Each of the next m
lines describes an event.

There are three different events described in different format shown below:

D x: The x-th village was destroyed.

Q x: The Army commands requested the number of villages that x-th
village was directly or indirectly connected with including itself.

R: The village destroyed last was rebuilt.

Output

Output the answer to each of the Army commanders’ request in order on a separate line.

Sample Input

  1. 7 9
  2. D 3
  3. D 6
  4. D 5
  5. Q 4
  6. Q 5
  7. R
  8. Q 4
  9. R
  10. Q 4

Sample Output

  1. 1
  2. 0
  3. 2
  4. 4
  5.  
  6. 题目的大概意思就是地道战。 D x 表示摧毁x点,R 表示修复最后一个被摧毁的点,Q x 表示查询包含x点的最大连续区间的长度是多少。
    这题主要是维护状态比较麻烦。
    对于每个节点,我们要除了储存它的左右边界,还要储存从区间左端点开始的最大连续区间长度(ls),从右端点开始的最大连续区间长度(rs),
    以及当前区间内的最大的连续长度(ms)。例如0100111ls=0,rs=3,ms=3.状态更新的细节写到代码注释里了。
    代码如下:
  1. #include <bits/stdc++.h>
  2. #define lson rt<<1
  3. #define rson rt<<1|1
  4. using namespace std;
  5. #define M 50050
  6. struct segTree
  7. {
  8. int l,r;
  9. int ls,rs,ms;
  10. }tree[M<<];
  11. void buildTree (int rt,int l,int r)
  12. {
  13. tree[rt].l=l,tree[rt].r=r;
  14. tree[rt].ls=tree[rt].rs=tree[rt].ms=r-l+;
  15. if (l==r)
  16. return ;
  17. int mid=(l+r)>>;
  18. buildTree(lson,l,mid);
  19. buildTree(rson,mid+,r);
  20. }
  21. void upDate(int rt,int x,int val)
  22. {
  23. if (tree[rt].l==tree[rt].r)
  24. {
  25. if (val==)
  26. tree[rt].ls=tree[rt].rs=tree[rt].ms=;
  27. else
  28. tree[rt].ls=tree[rt].rs=tree[rt].ms=;
  29. return ;
  30. }
  31. int mid=(tree[rt].l+tree[rt].r)>>;
  32. if (x<=mid)
  33. upDate(lson,x,val);
  34. else
  35. upDate(rson,x,val);
  36.  
  37. tree[rt].ls=tree[lson].ls;//父节点先继承左儿子的ls
  38. tree[rt].rs=tree[rson].rs;//父节点先继承右儿子的rs
  39.  
  40. tree[rt].ms=max(tree[lson].ms,tree[rson].ms);
  41. tree[rt].ms=max(tree[rt].ms,tree[lson].rs+tree[rson].ls);
  42. /*
  43. 父节点内当前的连续最大值是当前区间ls(1),rs(2),
  44. 与左儿子的rs右儿子ls(两部分在中间拼起来,3)三者的最大值
  45. */
  46. if (tree[lson].ls==tree[lson].r-tree[lson].l+)
  47. /*如果父节点的左儿子的ls等于左儿子的长度(满了),
  48. 则父节点的ls在继承左儿子ls的基础上还要加上右儿子的ls
  49. 例:1111 1101
  50. lson rson
  51. 父节点.ls=lson.ls(4)+rson.ls(2)=6;
  52. */
  53. tree[rt].ls+=tree[rson].ls;
  54. if (tree[rson].rs==tree[rson].r-tree[rson].l+)
  55. //同理如果右儿子的rs满了父节点的rs还要加上左儿子的rs
  56. tree[rt].rs+=tree[lson].rs;
  57. }
  58. int query (int rt,int x)
  59. {
  60. if (tree[rt].l==tree[rt].r||tree[rt].ms==||tree[rt].ms==tree[rt].r-tree[rt].l+)
  61. {
  62. return tree[rt].ms;
  63. //当查询到叶子节点,或当前区间ms为0或区间是满的,return
  64. }
  65. int mid=(tree[rt].l+tree[rt].r)>>;
  66. if (x<=mid)
  67. {
  68. if (x>=tree[lson].r-tree[lson].rs+)
  69. /* x如果在左儿子的右连续区间内
  70. lson 1111 1101 rson
  71. x
  72. 答案等于左儿子内包含x的区间(4)+右儿子的ls长度(2)=6
  73. */
  74. return query(lson,x)+ tree[rson].ls;
  75. else//否则只需查询左儿子
  76. return query(lson,x);
  77. }
  78. else
  79. {
  80. if (x<=tree[rson].l+tree[rson].ls-)//x在右儿子的左连续区间内
  81. return query(rson,x)+ tree[lson].rs;//答案等于右儿子内包含x的区间+左儿子rs
  82. else
  83. return query(rson,x);
  84. }
  85. }
  86. int s[M],top;//模拟一个栈,来处理最后一个被破坏的区间
  87. int main()
  88. {
  89. int m,n;
  90. char o[];
  91. //freopen("de.txt","r",stdin);
  92. while (~scanf("%d%d",&n,&m))
  93. {
  94. top=;
  95. buildTree(,,n);
  96. while (m--)
  97. {
  98. scanf("%s",o);
  99. int x;
  100. if (o[]=='D')
  101. {
  102. scanf("%d",&x);
  103. s[top++]=x;
  104. upDate(,x,);
  105. }
  106. else if (o[]=='Q')
  107. {
  108. scanf("%d",&x);
  109. printf("%d\n",query(,x));
  110. }
  111. else
  112. {
  113. if (x>)
  114. {
  115. x=s[--top];
  116. upDate(,x,);
  117. }
  118. }
  119. }
  120. }
  121. return ;
  122. }
  1.  
  1.  
  1.  

hdu 1540 Tunnel Warfare (线段树,维护当前最大连续区间)的更多相关文章

  1. hdu 1540 Tunnel Warfare(线段树区间统计)

    Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) T ...

  2. HDU 1540 Tunnel Warfare (线段树或set水过)

    题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少. 析:首先可以用set水过,set用来记录每个被破坏的村庄,然后查找时,只要查找左右两个端点好. 用线段 ...

  3. hdu 1540 Tunnel Warfare 线段树 单点更新,查询区间长度,区间合并

    Tunnel Warfare Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pi ...

  4. HDU 1540 Tunnel Warfare 线段树区间合并

    Tunnel Warfare 题意:D代表破坏村庄,R代表修复最后被破坏的那个村庄,Q代表询问包括x在内的最大连续区间是多少 思路:一个节点的最大连续区间由(左儿子的最大的连续区间,右儿子的最大连续区 ...

  5. HDU 1540 Tunnel Warfare (线段树)

    Tunnel Warfare Problem Description During the War of Resistance Against Japan, tunnel warfare was ca ...

  6. HDU 1540 Tunnel Warfare (线段树)

    题目大意: n 个村庄排列在一条直线上,相邻的村庄有地道连接,除首尾两个村庄外,其余村庄都有两个相邻的村庄.其中有 3 中操作 D x :表示摧毁编号为 x 的村庄,Q x:表示求出包含村庄 x 的最 ...

  7. hdu 1540 Tunnel Warfare 线段树 区间合并

    题意: 三个操作符 D x:摧毁第x个隧道 R x:修复上一个被摧毁的隧道,将摧毁的隧道入栈,修复就出栈 Q x:查询x所在的最长未摧毁隧道的区间长度. 1.如果当前区间全是未摧毁隧道,返回长度 2. ...

  8. hdu 1540 Tunnel Warfare 线段数区间合并

    Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) P ...

  9. HDU 1540 Tunnel Warfare(最长连续区间 基础)

    校赛,还有什么途径可以申请加入ACM校队?  Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/ ...

  10. hdu 1540 Tunnel Warfare (区间线段树(模板))

    http://acm.hdu.edu.cn/showproblem.php?pid=1540 Tunnel Warfare Time Limit: 4000/2000 MS (Java/Others) ...

随机推荐

  1. CALayer的mask属性

    可以对图层按path进行指定裁剪 //#import "ViewController.h" // //@interface ViewController () // //@end ...

  2. flutter中的命名路由

    命名路由是区别于基本路由的一种存在,方便于大型项目中路由的统一管理,现在,在前面基本路由的项目基础上实现实现命名路由. 使用步骤 路由配置 命名路由在使用前,需要在根组件main.dart中进行简单的 ...

  3. AT2070 Card Game for Three(组合数学)

    传送门 解题思路 前面的思路还是很好想的,就是要枚举最后一个\(a\)在哪出现算贡献,之后我先想的容斥,结果彻底偏了..后来调了很久发现自己傻逼了,似乎不能容斥,终于走上正轨23333.首先可以写出一 ...

  4. static、final修饰的变量和方法能否被继承的问题

    首先定义父类和子类 public class Parent { protected static String a = "static"; final String b = &qu ...

  5. outlook使用inline style回复邮件

    Reply with inline comments within the original message text When you reply to email messages in Outl ...

  6. Linux 下查看用户组信息

    1.id 通过id 可以直接查看到当前登陆用户的uid, group id , group name 等等.. 2.groups

  7. shell脚本——注释(单行注释 多行注释)

    参考 : https://blog.csdn.net/weixin_42167759/article/details/80703570 单行注释 以"#"开头的行就是注释,会被解释 ...

  8. 面试题22:链表中倒数第k个节点

    # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None ...

  9. 【html】 两栏对比网页,同时滚动

    有的时候需要左右对比环境,而且希望能同时滚动,如下这么拼接就可以了 <html> <head><meta http-equiv="content-type&qu ...

  10. md5加密 和拉钩网的登录

    #使用requests模块 #1.登录lagou #2.登录人人,保存个人首页 import requests from urllib import parse #hashlib是MD5加密的一个py ...