Tunnel Warfare

HDOJ-1540

  • 这题关于线段树的操作有一定的难度,需要较好的思维能力。
  • 关于题目的详细解答已经在代码中体现了。
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<string>
  5. #include<algorithm>
  6. #include<cmath>
  7. #include<vector>
  8. using namespace std;
  9. const int maxn=50004;
  10. int n,m;
  11. int llen[maxn<<2];//左端点起的最大长度
  12. int rlen[maxn<<2];//右端点起的最大长度
  13. void pushup(int id,int l,int r){
  14. int lc=id<<1;
  15. int rc=id<<1|1;
  16. int ch=r-l+1;//ch表示id(父亲)结点的覆盖长度
  17. llen[id]=llen[lc];//左端点起的最大长度等于左儿子左端点起的最大长度
  18. rlen[id]=rlen[rc];
  19. if(llen[id]==ch-(ch>>1))//如果左儿子最大长度为结点整个区间,那么父亲结点要加上右儿子左端点起的最大长度
  20. llen[id]+=llen[rc];
  21. if(rlen[id]==(ch>>1)) //如果右儿子最大长度为结点整个区间,那么父亲结点要加上左儿子右端点起的最大长度
  22. rlen[id]+=rlen[lc];
  23. }
  24. void build(int id,int l,int r){
  25. if(l==r){
  26. llen[id]=1;
  27. rlen[id]=1;
  28. return;
  29. }
  30. //长度全部初始化为结点覆盖的长度
  31. llen[id]=r-l+1;
  32. rlen[id]=r-l+1;
  33. int mid=(l+r)>>1;
  34. int lc=id<<1;int rc=id<<1|1;
  35. build(lc,l,mid);
  36. build(rc,mid+1,r);
  37. }
  38. void update(int id,int l,int r,int p,int v){
  39. if(l==r){
  40. llen[id]=v;
  41. rlen[id]=v;
  42. return;
  43. }
  44. int mid=(l+r)>>1;
  45. int lc=id<<1;
  46. int rc=id<<1|1;
  47. if(p<=mid){
  48. update(lc,l,mid,p,v);
  49. }else{
  50. update(rc,mid+1,r,p,v);
  51. }
  52. pushup(id,l,r);
  53. }
  54. int queryL(int id,int l,int r,int p,int q){//查询右边区间左端点起的最大长度
  55. if(p<=l&&q>=r){
  56. return llen[id];
  57. }
  58. int mid=(l+r)>>1;
  59. int lc=id<<1;
  60. int rc=id<<1|1;
  61. if(q<=mid){//表示待查询的区间完全在左边
  62. return queryL(lc,l,mid,p,q);
  63. }else if(p>mid){//表示待查询的区间完全在右边
  64. return queryL(rc,mid+1,r,p,q);
  65. }else{//mid在待查询区间之内
  66. int lans=queryL(lc,l,mid,p,mid);
  67. int rans=queryL(rc,mid+1,r,mid+1,q);
  68. if(lans==mid-p+1){//如果左区间最大长度为整个区间,这个时候才需要加上右边区间左端点起的最大长度
  69. return lans+rans;
  70. }else return lans;
  71. }
  72. }
  73. int queryR(int id,int l,int r,int p,int q){//查询右边区间左端点起的最大长度
  74. if(p<=l&&q>=r){
  75. return rlen[id];
  76. }
  77. int mid=(l+r)>>1;
  78. int lc=id<<1;
  79. int rc=id<<1|1;
  80. if(q<=mid){
  81. return queryR(lc,l,mid,p,q);
  82. }else if(p>mid){
  83. return queryR(rc,mid+1,r,p,q);
  84. }else{
  85. int lans=queryR(lc,l,mid,p,mid);
  86. int rans=queryR(rc,mid+1,r,mid+1,q);
  87. if(rans==q-mid){//同理,如果有区间的最大长度为整个区间,这个时候才需要加上左边区间右端点起的最大长度
  88. return lans+rans;
  89. }else return rans;
  90. }
  91. }
  92. int main(){
  93. while(cin>>n>>m){
  94. vector<int> v;
  95. build(1,1,n);
  96. for(int i=0;i<m;i++){
  97. char c;int x;
  98. cin>>c;
  99. if(c=='D'){//update
  100. cin>>x;
  101. v.push_back(x);
  102. update(1,1,n,x,0);
  103. }else if(c=='Q'){//query
  104. cin>>x;
  105. int ans=queryL(1,1,n,x,n)+queryR(1,1,n,1,x);//相当于查询左边区间右端点起最大长度加上右边区间左端点起最大长度
  106. cout<<(ans>0?ans-1:0)<<endl;
  107. }else if(c=='R'&&v.size()>0){//update
  108. x=v[v.size()-1];
  109. v.pop_back();
  110. update(1,1,n,x,1);
  111. }
  112. }
  113. }
  114. return 0;
  115. }

HDOJ-1540(线段树+较复杂的单点修改和区间查询)的更多相关文章

  1. 线段树:Segment Tree(单点修改/区间修改模板) C++

    线段树是非常有效的数据结构,可以快速的维护单点修改,区域修改,查询最大值,最小值等功能. 同时,它也很重要.如果有一天比赛,你卡在了一道线段树模板题目上,这就真的尴尬了.不过,随着时代的进步,题目也越 ...

  2. P3374 【模板】树状数组 1 单点修改与区间查询

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  3. Billboard HDU - 2795(树状数组,单点修改,区间查询)

    题目链接:https://vjudge.net/problem/HDU-2795 思路:h = 1e9行不通,因为广告是1*w的,所以n个广告最多只需要 h = n的高度,那么h=2e5就可以接受了. ...

  4. 【模板】cdq分治代替树状数组(单点修改,区间查询)

    #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #in ...

  5. 【算法系列学习】线段树vs树状数组 单点修改,区间查询 [kuangbin带你飞]专题七 线段树 A - 敌兵布阵

    https://vjudge.net/contest/66989#problem/A 单点修改,区间查询 方法一:线段树 http://www.cnblogs.com/kuangbin/archive ...

  6. HUD.2795 Billboard ( 线段树 区间最值 单点更新 单点查询 建树技巧)

    HUD.2795 Billboard ( 线段树 区间最值 单点更新 单点查询 建树技巧) 题意分析 题目大意:一个h*w的公告牌,要在其上贴公告. 输入的是1*wi的w值,这些是公告的尺寸. 贴公告 ...

  7. HDU - 1166 敌兵布阵 方法一:(线段树+单点修改,区间查询和) 方法二:利用树状数组

    C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于 ...

  8. ZOJ - 1610 Count the Colors(线段树区间更新,单点查询)

    1.给了每条线段的颜色,存在颜色覆盖,求表面上能够看到的颜色种类以及每种颜色的段数. 2.线段树区间更新,单点查询. 但是有点细节,比如: 输入: 2 0 1 1 2 3 1 输出: 1 2 这种情况 ...

  9. 校内模拟赛T5:连续的“包含”子串长度( nekameleoni?) —— 线段树单点修改,区间查询 + 尺取法合并

    nekameleoni 区间查询和修改 给定N,K,M(N个整数序列,范围1~K,M次查询或修改) 如果是修改,则输入三个数,第一个数为1代表修改,第二个数为将N个数中第i个数做修改,第三个数为修改成 ...

随机推荐

  1. hdu5407CRB and Candies (逆元+数学公式)

    Problem Description CRB has N different candies. He is going to eat K candies. He wonders how many c ...

  2. 【Java】位操作符

    位运算符 java支持的位运算符有7个,分为两类:位逻辑运算和移位运算.位逻辑运算符包括按位取反(~).按位与(&).按位或(|)和按位异或(^)4种,.移位运算符包括左移(<<) ...

  3. ElasticSearch 7.x 学习

    目录 ElasticSearch 7.x 一.前言 1.1.正向索引和倒排索引 1.1.1.正向索引 1.1.2.倒排索引 二.安装 三.ES 基本概念 3.1.索引 3.2.文档 3.4.mappi ...

  4. 牛客网-n的约数【dfs】

    题目描述:戳这里 解题思路:这题思路好想,n最多也就是20个不同的素数相乘,把所有可能的素数找到,然后枚举素数个数就行了. n = p1^q1 + p2^q2 + p3 ^q3 + ... + pi ...

  5. 使用LCX进行内网端口转发

    Lcx.exe是一个端口转发工具,相当于把目标服务器A上的3389端口转发到具有外网ip地址的B机上(即我们自己的主机或是已经控制的主机),这样链接B机的3389端口就相当于链接A机的3389端口了, ...

  6. u-boot 移植 --->2、在u-boot新增SOC和板子

    本次主要是要新增一个samsung的芯片到u-boot中,网上查阅资料发现s5pc1xx是与手上的S5PV210的友善的Tiny版子寄存器兼容的比较多,所以就准备以他为基础增加一个我的板子的支持到u- ...

  7. console.warn All In One

    console.warn All In One ️ FBI 警告 // console 简介 // consoleCtt: function () { // if (window.console &a ...

  8. no need jQuery anymore & You don't need jQuery anymore!

    no need jQuery anymore & You don't need jQuery anymore! "use strict"; /** * * @author ...

  9. iPadOS 14 memoji 无法使用 bug

    iPadOS 14 memoji 无法使用 bug iPadOS 14 bug refs 如何在 iPhone 和 iPad Pro 上使用动话表情 https://support.apple.com ...

  10. Redis 大 key 问题 & 问题分析 & 解决方案

    Redis 大 key 问题 & 问题分析 & 解决方案 Redis 什么是 Redis 大 key 单个key 存储的 value 很大 hash, set,zset,list 结构 ...