【题意】

一段区间初始均为可行。有两个操作:

1→找出长度为w的一段可行区间,如果存在则返回这个可行区间最靠左的情况,并将该区间设为不可行;

2→将区间[a,b]设为可行区间。

【思路】

经典的线段树合并,代码依旧用的是神犇的线段树模板。详见注释。

【错误点】

延迟标记的时候,忘记把cover清为-1了,导致RE!

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cstdlib>
  6 using namespace std;
  7 #define lson l,m,rt<<1
  8 #define rson m+1,r,rt<<1|1
  9 const int MAXN=55555+10;
 10 int cover[MAXN<<2];//-1表示当前没有覆盖标记,1表示均覆盖为不可行,0表示均覆盖为可行
 11 int lsum[MAXN<<2];//该区间从左起连续的可用区间长度的最大值
 12 int msum[MAXN<<2];//该区间中连续的可用区间长度的最大值
 13 int rsum[MAXN<<2];//该区间从右起连续的可用区间长度的最大值
 14
 15 void PushUp(int rt,int m)
 16 {
 17     lsum[rt]=lsum[rt<<1];
 18     if (lsum[rt]==m-(m>>1)) lsum[rt]+=lsum[rt<<1|1];
 19     /*如果左孩子全部为可用区间,那么加上右孩子的左端*/
 20     rsum[rt]=rsum[rt<<1|1];
 21     if (rsum[rt]==m>>1) rsum[rt]+=rsum[rt<<1];
 22     /*同上*/
 23     msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]) , rsum[rt<<1]+lsum[rt<<1|1]);
 24     /*该区间的可用区间可能是:左孩子最大的可用区间、有孩子最大的可用区间,和跨越左右孩子加在一起的可用区间*/
 25 }
 26
 27 void PushDown(int rt,int m)
 28 {
 29     if (cover[rt]!=-1)
 30     {
 31         cover[rt<<1]=cover[rt<<1|1]=cover[rt];
 32         if (cover[rt]==1)
 33         {
 34             msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=0;
 35             msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=0;
 36         }
 37         else
 38         {
 39             msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=m-(m>>1);
 40             msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=m>>1;
 41         }
 42         cover[rt]=-1;
 43         /*千万不要忘记将rt清为-1*/
 44     }
 45 }
 46
 47
 48 int query(int w,int l,int r,int rt)
 49 {
 50     if (l==r) return l;
 51     PushDown(rt,r-l+1);
 52     int m=(l+r)>>1;
 53     if (msum[rt<<1]>=w) return(query(w,lson));
 54     /*由于要找最左边的区间,按照左孩子、跨越两者、有孩子的顺序查找*/
 55     if (rsum[rt<<1]+lsum[rt<<1|1]>=w) return(m-rsum[rt<<1]+1);
 56     return(query(w,rson));
 57 }
 58
 59 void update(int L,int R,int o,int l,int r,int rt)
 60 {
 61     if (L<=l && r<=R)
 62     {
 63         cover[rt]=o;
 64         if (o==1) msum[rt]=lsum[rt]=rsum[rt]=0;
 65             else msum[rt]=lsum[rt]=rsum[rt]=r-l+1;
 66         return;
 67     }
 68     PushDown(rt,r-l+1);//这里是l和r,不要写成L和R
 69     int m=(l+r)>>1;
 70     if (L<=m) update(L,R,o,lson);
 71     if (m<R)  update(L,R,o,rson);
 72     PushUp(rt,r-l+1);
 73 }
 74
 75 void build(int l,int r,int rt)
 76 {
 77     msum[rt]=lsum[rt]=rsum[rt]=r-l+1;
 78     cover[rt]=-1;
 79     if (l==r) return;
 80     int m=(l+r)>>1;
 81     build(lson);
 82     build(rson);
 83 }
 84
 85 int main()
 86 {
 87     int n,m;
 88     scanf("%d%d",&n,&m);
 89     build(1,n,1);
 90     for (int i=0;i<m;i++)
 91     {
 92         int op;
 93         scanf("%d",&op);
 94         if (op==1)
 95         {
 96             int w;
 97             scanf("%d",&w);
 98             if (msum[1]<w) cout<<0<<endl;
 99             /*如果根的可用区间已经小于w,那么一定是找不到长度为w的可用区间*/
100                 else
101                 {
102                       int p=query(w,1,n,1);
103                       cout<<p<<endl;
104                       update(p,p+w-1,1,1,n,1);
105                 }
106         }
107         else
108         {
109             int u,v;
110             scanf("%d%d",&u,&v);
111             update(u,u+v-1,0,1,n,1);
112         }
113     }
114     return 0;
115 }

转载于:https://www.cnblogs.com/iiyiyi/p/5172879.html

【线段树区间合并】POJ3667-Hotel相关推荐

  1. poj-3667(线段树区间合并)

    题目链接:传送门 参考文章:传送门 思路:线段树区间合并问题,每次查询到满足线段树的区间最左值,然后更新线段树. #include<iostream> #include<cstdio ...

  2. 树链剖分——线段树区间合并bzoj染色

    线段树区间合并就挺麻烦了,再套个树链就更加鬼畜,不过除了代码量大就没什么其他的了.. 一些细节:线段树每个结点用结构体保存,pushup等合并函数改成返回一个结构体,这样好写一些 struct Seg ...

  3. SPOJ GSS3-Can you answer these queries III-分治+线段树区间合并

    Can you answer these queries III SPOJ - GSS3 这道题和洛谷的小白逛公园一样的题目. 传送门: 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间 ...

  4. Tunnel Warfare(HDU1540+线段树+区间合并)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540 题目: 题意:总共有n个村庄,有q次操作,每次操作分为摧毁一座村庄,修复一座村庄,和查询与询问的 ...

  5. CodeForces - 1539F Strange Array(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的序列,规定位置 iii 的贡献是:设 x=a[i]x=a[i]x=a[i],选择一个包含 iii 的区间 [l,r][l,r][l,r],将其中 ...

  6. 牛客 - 求函数(线段树+区间合并/线段树+矩阵维护)

    题目链接:点击查看 题目大意:现在有 n 个函数,每个函数都是诸如 f( x ) = k * x + b 的形式,只是每个函数的 k 和 b 都是相互独立的,现在给出两个操作: 1 pos k b:将 ...

  7. 2021牛客暑期多校训练营7 xay loves monotonicity 线段树区间合并

    传送门 文章目录 题意: 思路: 题意: 题面挺绕口的,还是看原题比较好. 大概的意思就是让你从给定的区间中选择一个以左端点为起点的一个上升子序列,让后将这些下标存下来,在bbb中将这些位置拿出来后, ...

  8. HDU3308 线段树区间合并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 ,简单的线段树区间合并. 线段树的区间合并:一般是要求求最长连续区间,在PushUp()函数中实 ...

  9. HDU1540(线段树区间合并)

    很经典的一道题,线段树区间合并非常好的一道入门题,每个节点保存区间连续1的最大左串长度,最大右串长度,以及区间最大长度(常规的三种信息维护),更新操作时注意push_up函数,针对不同的问题,push ...

  10. Hotel POJ - 3667(线段树 + 区间合并

    题意: 给定长度为n的区间 ,有2个操作: 操作1: 在区间中靠左放k个元素,输出新放入元素中最左边的位置,如果放不下输出 0: 操作2 : 清空 l 到 l+w-1这一段区间的元素 这里有一个状态转 ...

最新文章

  1. 在DWR中实现直接获取一个JAVA类的返回值的两种方法
  2. k8s集群dns问题解决办法
  3. Eclipse文件夹导入Jar
  4. Application log save debug - how log data is persisted to database table
  5. Verilog HDL中模块参数传递的方法
  6. three20 TTTableViewController + TTActionSheetController
  7. 计算机学院学生会宣传稿,计算机与信息工程学院学生会
  8. Task10.Bert
  9. 分享:Python中的位运算符
  10. Mac ndk编译for Android
  11. 八、Python 之内置函数(。。。)
  12. matlab中小波工具箱,matlab小波分析工具箱使用教程
  13. 批量doc转docx的两种方法--Office Migration Planning Manager使用、插件使用
  14. 显示搜索dota2协调服务器,搜索dota2游戏协调服务器中【操作方式】
  15. bzoj #1854 游戏(二分图匹配)
  16. 360手机号码归属地查询抓取、免费稳定高效手机号码归属地查询
  17. 第三章 分布式扩展(一)
  18. mlir toy 教程(1)
  19. deepin系统安装nginx
  20. Nero8直接把APE带CUE映像文件刻录CD方法(转帖)

热门文章

  1. oracle乘法运算,乘法运算
  2. 《计算机视觉中的数学方法》
  3. 8051芯片选型 - 新唐MS51
  4. Python XlsxWriter创建xlsx格式的Excel文件
  5. 【USACO 2020 January Silver】Loan Repayment
  6. 【JSD2209-DAY05】for、while、数组(上)
  7. 微信支付商户号的调研
  8. 青春期玩游戏不想上学怎么办?
  9. 论文阅读ICLR2020《ADAPTIVE STRUCTURAL FINGERPRINTS FOR GRAPH ATTENTION NETWORKS》
  10. cv2.error: OpenCV(4.5.1) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-buil windows下的解决方案