题目大意:
有一排标号1-N的房间。
操作一:询问是不是有连续长度为a的空房间,有的话住进最左边(占用a个房间)
操作二:将[a,a+b-1]的房间清空(腾出b个房间)
思路:记录每个区间中“靠左”“靠右”“中间”的空房间
线段树操作:update:区间替换
query:询问满足条件的最左端点

题目链接:

http://vjudge.net/problem/viewProblem.action?id=10354

题目操作:

因为这里找从最左边住起的房间,所以这里不能像常规地写query函数那样写了,终于发现自己只会套模板的下场的悲哀了,智商拙计啊T T

而且你在query函数,因为要尽可能找左边的房间,所以要从左边先递归

1.

int query(int cur,int x,int y,int w)
{
    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    if(x==y) return x;  //这里是表示找到树的底层无叶节点了就结束函数,同时也防止找不到点,其实这里如果找不到所求点的话,会不断进入右子树最后抵达最大的子节点返回
    pushdown(cur,x,y);
    if(mc[cur<<1]>=w) return query(ls,x,mid,w);  //如果左侧能找到满足的点,我们不断朝左侧进行递归
    else if(rc[cur<<1]+lc[cur<<1|1]>=w) return mid-rc[cur<<1]+1;//左侧不成立我们在开始找中间并在一起形成的房间的最左侧点
    return query(rs,mid+1,y,w);  //左侧中间都不成立,那么只能进入右子树进行找点
}
因为这个query函数必然有返回值,所以,我们在主函数中必须先进行判断能否找到适合的一连串的房间,然后再进行ans=query(1,1,n,w)操作以及后面的房间入住的覆盖操作。

这个判断很简单 1为线段树根节点,所以mc[1]其实是最大的连续最长房间,if(mc[1]>=w)这个判断执行就可以了

这里介绍一下puts("0"):
puts()函数用来向标准输出设备(屏幕)写字符串并换行,其调用方式为,puts(s);其中s为字符串字符(字符串数组名或字符串指针)。

所以这道题puts("0");就输出了不存在的情况

2.

当然我也可以换种方式在query的函数里面进行一下小小的修改,使得它在不能找到房间的时候输出-1;

int query(int cur,int x,int y,int w)
{
    int mid=(x+y)>>1,ls=cur<<1,rs=cur<<1|1;
    if(x==y) return mc[cur]<w?-:x; //在这修改一下,然后直接在main函数中判断为-1,那么输出0即可
    pushdown(cur,x,y);
    if(mc[cur<<1]>=w) return query(ls,x,mid,w);
    else if(rc[cur<<1]+lc[cur<<1|1]>=w) return mid-rc[cur<<1]+1;
    return query(rs,mid+1,y,w);
}

总代码如下:

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 50010
#define L ls,x,mid
#define R rs,mid+1,y
int rev[N<<],lc[N<<],rc[N<<],mc[N<<];
void update(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
lc[cur]=lc[ls],rc[cur]=rc[rs];
mc[cur]=max(mc[ls],mc[rs]);
mc[cur]=max(mc[cur],rc[ls]+lc[rs]);
if(lc[ls]==mid-x+) lc[cur]=lc[ls]+lc[rs];
if(rc[rs]==y-mid) rc[cur]=rc[rs]+rc[ls];
}
void build(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
rev[cur]=-;
if(x==y){
lc[cur]=rc[cur]=mc[cur]=;
return;
}
build(ls,x,mid);
build(rs,mid+,y);
update(cur,x,y);
}
void pushdown(int cur,int x,int y)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(rev[cur]!=-){
if(rev[cur]==){
rev[ls]=rev[rs]=;
lc[ls]=rc[ls]=mc[ls]=lc[rs]=rc[rs]=mc[rs]=;
rev[cur]=-;
}
else if(rev[cur]==){
rev[ls]=rev[rs]=;
lc[ls]=rc[ls]=mc[ls]=mid-x+;
lc[rs]=rc[rs]=mc[rs]=y-mid;
rev[cur]=-;
}
}
}
void change(int cur,int x,int y,int s,int t,int v)
{
int mid=(x+y)/,ls=cur<<,rs=cur<<|;
if(x>=s&&y<=t){
rev[cur]=v;
lc[cur]=rc[cur]=mc[cur]=v?:y-x+;
return;
}
pushdown(cur,x,y);
if(mid>=s) change(ls,x,mid,s,t,v);
if(mid+<=t) change(rs,mid+,y,s,t,v);
update(cur,x,y);
}
int query(int cur,int x,int y,int w)
{
int mid=(x+y)>>,ls=cur<<,rs=cur<<|;
if(x==y) return x;
pushdown(cur,x,y);
if(mc[cur<<]>=w) return query(ls,x,mid,w);
else if(rc[cur<<]+lc[cur<<|]>=w) return mid-rc[cur<<]+;
return query(rs,mid+,y,w);
}
int main()
{
int n,m,op,a,b;
while(scanf("%d%d",&n,&m)!=EOF){
build(,,n);
for(int i=;i<m;i++){
scanf("%d",&op);
if(op==){
scanf("%d",&a);
if(mc[]<a) puts("");
else{
int ans=query(,,n,a);
printf("%d\n",ans);
change(,,n,ans,ans+a-,);
}
}
else{
scanf("%d%d",&a,&b);
change(,,n,a,a+b-,);
}
}
}
return ;
}

POJ 3667 线段树的区间合并简单问题的更多相关文章

  1. POJ 3667 线段树区间合并裸题

    题意:给一个n和m,表示n个房间,m次操作,操作类型有2种,一种把求连续未租出的房间数有d个的最小的最左边的房间号,另一个操作时把从x到x+d-1的房间号收回. 建立线段树,值为1表示未租出,0为租出 ...

  2. 线段树的区间合并 B - LCIS

    B - LCIS HDU - 3308 这个是一个很简单很明显的线段树的区间合并,不过区间合并的题目都还是有点难写,建议存个板子. #include <cstdio> #include & ...

  3. 线段树:CDOJ1592-An easy problem B (线段树的区间合并)

    An easy problem B Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Pr ...

  4. CodeForces - 587E[线段树+线性基+差分] ->(线段树维护区间合并线性基)

    题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 做法一:对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线 ...

  5. Codeforces Round #222 (Div. 1) D. Developing Game 线段树有效区间合并

    D. Developing Game   Pavel is going to make a game of his dream. However, he knows that he can't mak ...

  6. POJ 3667 & HDU 3308 & HDU 3397 线段树的区间合并

    看到讲课安排上 线段树有一节课"区间合并" 我是迷茫的 因为并没有见过 然后了解了一下题目 发现以前写过 还是很麻烦的树链剖分 大概是 解决带修改的区间查询"连续问题&q ...

  7. POJ 3667 线段树区间合并

    http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html 用线段树,首先要定义好线段树的节点信息,一般看到一个问题,很难很 ...

  8. POJ 2750 Potted Flower(线段树的区间合并)

    点我看题目链接 题意 : 很多花盆组成的圆圈,每个花盆都有一个值,给你两个数a,b代表a位置原来的数换成b,然后让你从圈里找出连续的各花盆之和,要求最大的. 思路 :这个题比较那啥,差不多可以用DP的 ...

  9. HDU_3308_线段树_区间合并

    LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

随机推荐

  1. codeblock 16.01

    1.不希望for (int i = 1; i <= n; ++i) { } 中间按下去后,自动缩进到中间,只缩进到下一行. 可以去掉其中一个. 2.不自动完成,就是出现一个括号后不补充另一个. ...

  2. 009全志R16平台tinav3.0下编译不过的问题

    009全志R16平台tinav3.0下编译不过的问题 2018/11/13 11:39 版本:V1.0 开发板:SC3817R SDK:tina v3.0 1.01原始编译全志r16平台tinav3. ...

  3. JMeter进入接口压力测试

    关键字: Jmeter.单接口.压力测试.插件监听.服务器端 摘要: 使用Jmeter对单个接口进行压力测试:监听并发量对接口响应时间.服务器资源占量.Jmeter本身只能获取到Tomcat的状态,所 ...

  4. IOS问题

    #import "EXFifthViewController.h" @interface EXFifthViewController () @end @implementation ...

  5. 洛谷 P1803 凌乱的yyy

    题目背景 快noip了,yyy很紧张! 题目描述 现在各大oj上有n个比赛,每个比赛的开始.结束的时间点是知道的. yyy认为,参加越多的比赛,noip就能考的越好(假的) 所以,他想知道他最多能参加 ...

  6. nodejs,python,sublime和Eclipse的包管理器

    Python的包管理器叫pip. 首先安装Python运行环境Python 3.7.0:https://www.python.org/downloads/release/python-370/ Pyt ...

  7. cmd命令002

    cd..--> 返回上一级目录 cd\ --> 返回根目录"cd /d e:"--> 将当前盘符切换到e盘,"cd users/admin"- ...

  8. New Arrival MB SD Connect Compact 5 (MB SD C4) Star Diagnosis

    MB SD Connect Compact 5 has same function as SD C4 but with new design, support both cars and trucks ...

  9. PHP07 函数

    学习要点 函数的定义 自定义函数 函数的工作原理和结构化编程 PHP变量范围 声明及应用各种形式的PHP函数 递归函数 使用自定义函数库 匿名函数和闭包 常用PHP系统函数 PHP7函数新特性 函数的 ...

  10. 《3+1团队》【Alpha】Scrum meeting 4

    项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 3+1团队 团队博客地址 https://home.cnblogs.com/u/3-1group ...