这题的意思是现在有一些村庄成一条直线排列,现在有三个操作,D:摧毁一个指定的村庄,Q:询问与指定村庄相连的村庄个数,

就是这个村庄向左和向右数村庄数量,遇到尽头或损坏的村庄为止,这个就是与这个村庄相连的村庄数量,当然,如果指定村庄已经被摧毁,则数量为0。R:把最后摧毁的那一个村庄恢复。在这里D操作和R操作都可以看成对线段树的单点修改,只是执行的操作不同,

最主要的是如何找和指定村庄相连的村庄数量,刚刚做的时候我很纠结,看了别人博客后...  我们可以定义一个max1和一个min1,表示这个区间里的最大值和最小值(max1初始化为-1,min1初始化为无穷大),这样一开始就是没有左右边界,如果某个村庄被摧毁,则把他的max1和min1都变成他的节点值,(自己体会一下下)

如果我们想找a村庄的的相连村庄数目,惯性思维是想一次性就把左右两个边界求出来,后来才发现我们其实可以用两次区间查询来分别找到a的左边界和右边界,query1(1,a,1)和query2(a,n,1)就是找区间1到a的的最大值和区间a到n的最小值,然后存一下这两个边界,最后相减。

具体可以看看代码:

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<algorithm>
  4. #include<stack>
  5. using namespace std;
  6. #define inf 0x3f3f3f
  7. struct node{
  8. int l,r,min1,max1;
  9. }str[*+];
  10. stack<int>s;
  11. int n,m,k,t,a,b;
  12. int start,end1;
  13. char ss[];
  14. void build(int l,int r,int k)
  15. {
  16. str[k].l=l;
  17. str[k].r=r;
  18. str[k].max1=-;
  19. str[k].min1=inf;
  20. if(l==r)
  21. {
  22. return;
  23. }
  24. int mid=(l+r)/;
  25. build(l,mid,k*);
  26. build(mid+,r,k*+);
  27. str[k].max1=max(str[k*].max1,str[k*+].max1);
  28. str[k].min1=min(str[k*].min1,str[k*+].min1);
  29. }
  30. void change_point1(int k)//摧毁a点
  31. {
  32. if(str[k].l==str[k].r&&str[k].l==a)
  33. {
  34. str[k].max1=str[k].l;
  35. str[k].min1=str[k].l;
  36. return;
  37. }
  38. int mid=(str[k].l+str[k].r)/;
  39. if(a<=mid)
  40. change_point1(k*);
  41. else
  42. change_point1(k*+);
  43. str[k].max1=max(str[k*].max1,str[k*+].max1);
  44. str[k].min1=min(str[k*].min1,str[k*+].min1);
  45. }
  46. void change_point2(int k)//恢复a点
  47. {
  48. if(str[k].l==str[k].r&&str[k].l==a)
  49. {
  50. str[k].max1=-;
  51. str[k].min1=inf;
  52. return;
  53. }
  54. int mid=(str[k].l+str[k].r)/;
  55. if(a<=mid)
  56. change_point2(k*);
  57. else
  58. change_point2(k*+);
  59. str[k].max1=max(str[k*].max1,str[k*+].max1);
  60. str[k].min1=min(str[k*].min1,str[k*+].min1);
  61. }
  62. void query1(int l,int r,int k)//找a点的左边界
  63. {
  64. if(str[k].l>=l&&str[k].r<=r)
  65. {
  66. start=max(str[k].max1,start);
  67. return;
  68. }
  69. int mid=(str[k].l+str[k].r)/;
  70. if(l<=mid)
  71. query1(l,r,k*);
  72. if(r>mid)
  73. query1(l,r,k*+);
  74. }
  75. void query2(int l,int r,int k)//找a点的右边界
  76. {
  77. if(str[k].l>=l&&str[k].r<=r)
  78. {
  79. end1=min(end1,str[k].min1);
  80. return;
  81. }
  82. int mid=(str[k].l+str[k].r)/;
  83. if(l<=mid)
  84. query2(l,r,k*);
  85. if(r>mid)
  86. query2(l,r,k*+);
  87. }
  88. int main()
  89. {
  90. while(scanf("%d%d",&n,&m)!=EOF)
  91. {
  92. build(,n,);
  93. while(!s.empty())
  94. s.pop();
  95. for(int i=;i<m;i++)
  96. {
  97. scanf("%s",ss);
  98. if(ss[]=='D')
  99. {
  100. scanf("%d",&a);
  101. change_point1();
  102. s.push(a);
  103. }
  104. else if(ss[]=='Q')
  105. {
  106. scanf("%d",&a);
  107. start=-;
  108. end1=inf;
  109. query1(,a,);
  110. query2(a,n,);
  111. if(start==-)//特判一下
  112. start=;
  113. if(end1==inf)
  114. end1=n+;
  115. int ans=end1-start-;
  116.  
  117. if(start==end1)
  118. ans=;
  119. printf("%d\n",ans);
  120. }
  121. else if(ss[]=='R')
  122. {
  123. if(!s.empty())
  124. {
  125. a=s.top();
  126. change_point2();
  127. s.pop();
  128. }
  129. }
  130. }
  131. }
  132. return ;
  133. }

hdu 1540 线段树的更多相关文章

  1. HDU - 1540 线段树的合并

    这个题题意我大概解释一下,就是一开始一条直线,上面的点全是联通的,有三种操作 1.操作D把从左往右第x个村庄摧毁,然后断开两边的联通. 2.询问Q节点相联通的最长长度 3.把最后破坏的村庄重建. 这个 ...

  2. HDU 1540<线段树,区间并>

    题目连接 参考 题意: 维护各个点的连续的最大连续长度. 思路: 主要是维护一个区间的三个变量ll,f[i].l为起点向右的最大连续 长度,rl:f[i].r为起点向左的最大连续长度,ml:[l,r] ...

  3. I - Tunnel Warfare HDU - 1540 线段树最大连续区间

    题意  :一段区间  操作1 切断点 操作2 恢复最近切断的一个点 操作3 单点查询该点所在最大连续区间 思路:  主要是push_up :  设区间x 为母区间  x<<1 ,x< ...

  4. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  5. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  7. hdu 3397 线段树双标记

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  8. hdu 4578 线段树(标记处理)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) ...

  9. hdu 4533 线段树(问题转化+)

    威威猫系列故事——晒被子 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

随机推荐

  1. mac 关于默认python2下的pip,和python3下pip 的坑

    pip是常用的python包管理工具,类似于java的maven.用python的同学,都离不开pip. 1.在Python2.7的安装包中,easy_install.py是默认安装的,而pip需要手 ...

  2. jquery接触初级-----juqery DOM操作 之二

    DOm 操作之: 1.1  children(),这个函数只是查找元素的子元素,而不考虑其他后代元素 <body> <p title="请选择你最喜欢的水果"&g ...

  3. Java读写hdfs上的avro文件

    1.通过Java往hdfs写avro文件 import java.io.File; import java.io.IOException; import java.io.OutputStream; i ...

  4. Oracle问题小结

    1.win8.1安装Oracle11g后,重启电脑,出现黑屏. 解决办法:安全模式下,找到以oracle开头的全部服务,所有“自动”或者“自动(延迟启动)”的都设置为“手动”,只需要开启OracleO ...

  5. UNITY 优化之带Animator的Go.SetActive耗时问题,在手机上,这个问题似乎并不存在,因为优化了后手机上运行帧率并未明显提升

    UNITY 优化之带Animator的Go.SetActive耗时问题,在手机上,这个问题似乎并不存在,因为优化了后手机上运行帧率并未明显提升 经确认,这个问题在手机上依然存在,不过占的比例非常小.因 ...

  6. shell命令中用source 和sh(或者bash)执行脚本的区别,以及export的作用

    用户登录到Linux系统后,系统将启动一个用户shell,我们暂且称这个shell为shell父. 在这个shell父中,可以使用shell命令或声明变量,也可以创建并运行shell脚本程序. 当使用 ...

  7. SQL 语句 写法

    SELECT * FROM article where  userid=4 order by sort asc LIMIT 0,10; 先根据写where 条件,再排序,在LIMIT.

  8. vscode vue 格式化 和emmet 提示

    ctrl+shift+p打开用户默认设置 设置vetur插件 "vetur.validation.template": false, "vetur.format.defa ...

  9. Android 操作UI线程的一些方法

    我们经常会在后台线程中去做一些耗时的操作,比如去网络取数据.但是当数据取回来,需要显示到页面上的时候,会遇到一些小麻烦,因为我们都知道,android的UI页面是不允许在其他线程直接操作的.下面总结4 ...

  10. ArcGIS案例学习笔记3_1_地理配准案例_目视找点

    ArcGIS案例学习笔记3_1_地理配准案例_目视找点 计划时间:第3天上午 方法:地理配准/添加链接点/左键/右键/输入坐标 数据:江苏省.zip 矢量:省界,市界,GPS WGS84 地理坐标系 ...