https://www.luogu.org/problem/P2894

#include<cstdio>
#include<iostream>
using namespace std;
struct ben
{
int lmax,rmax,len,sum,lz;
}tr[400005];
void bt(int x,int l,int r)//建树
{
tr[x].lz=0;//标记清空
tr[x].sum=tr[x].len=tr[x].lmax=tr[x].rmax=r-l+1;//区间连续,区间长度,左端点连续,右端点连续都初始化成区间的长度。(因为所有房间都是空的
if(l==r)//如果到了叶子节点
{
return ;//返回
}
int mid=(l+r)/2;
bt(x*2,l,mid);
bt(x*2+1,mid+1,r);
//左右建子节点
}
void down(int x)//标记下放
{
if(tr[x].lz==0)return ;//如果没有标记,直接返回
if(tr[x].lz==1)//如果是要开房
{
tr[x*2].lz=tr[x*2+1].lz=1;//左右子节点都要标记上开房
tr[x*2].rmax=tr[x*2].lmax=tr[x*2].sum=0;
tr[x*2+1].rmax=tr[x*2+1].lmax=tr[x*2+1].sum=0;
//左右子节点因为已经开房而没有空房都变成0
}
if(tr[x].lz==2)//如果要退房
{
tr[x*2].lz=tr[x*2+1].lz=2;////左右子节点都要标记上退房
tr[x*2].rmax=tr[x*2].lmax=tr[x*2].sum=tr[x*2].len;
tr[x*2+1].rmax=tr[x*2+1].lmax=tr[x*2+1].sum=tr[x*2+1].len;
//此区间已经全为空房,所有直接都等于len即可
}
tr[x].lz=0;//要把父节点的标记清空
}
void renew(int x)//更新节点信息
{
if(tr[x*2].sum==tr[x*2].len)//如果左子节点全为空房
{
tr[x].lmax=tr[x*2].sum+tr[x*2+1].lmax;//那么父节点的左端最大连续为左子区间加上右子区间从左的最大连续
}
else
{
tr[x].lmax=tr[x*2].lmax;//否则就是沿用左从左
}
if(tr[x*2+1].sum==tr[x*2+1].len)//右边同理
{
tr[x].rmax=tr[x*2+1].sum+tr[x*2].rmax; }
else
{
tr[x].rmax=tr[x*2+1].rmax;
}
tr[x].sum=max(max(tr[x*2].sum,tr[x*2+1].sum),tr[x*2].rmax+tr[x*2+1].lmax);//最大连续的是左区间或右区间或左+右中最大的
}
void change_interval(int x,int l,int r,int tag,int L,int R)//区间修改,tag=1表示开房,tag=2表示退房
{
down(x);//下放懒标记
if(L<=l&&r<=R)//当前要查`询的区间如果在区间内
{
if(tag==1)
{
tr[x].sum=tr[x].lmax=tr[x].rmax=0;//开房就没有连续
}
else
{
tr[x].sum=tr[x].lmax=tr[x].rmax=tr[x].len;//退房就全是连续
}
tr[x].lz=tag;//打个懒标记
return ; //别忘返回,因为在整个查询区间内
}
int mid=(l+r)/2;
if(L<=mid)change_interval(x*2,l,mid,tag,L,R);
if(R>mid)change_interval(x*2+1,mid+1,r,tag,L,R);
renew(x);//更新当前节点 信息
}
int ask(int x,int l,int r,int ans)//查询有没有那么多连续的空房间
{
down(x);//下放懒标记
if(l==r)return l;//到叶子了,直接反回
int mid=(l+r)/2;
if(tr[x*2].sum>=ans)return ask(x*2,l,mid,ans);//如果左边就够用了 ,那么去左边找 (不要忘了是return !!!!!!!
if(tr[x*2].rmax+tr[x*2+1].lmax>=ans)return mid-tr[x*2].rmax+1;//否则左+右够了,那么就找左加右那个端点
return ask(x*2+1,mid+1,r,ans);//再否则就只能在右区间找了
}
int main()
{
int n,m,opt,x,y;
scanf("%d%d",&n,&m);
bt(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&opt,&x);
if(opt==1)
{
if(tr[1].sum>=x)
{
int left=ask(1,1,n,x);
printf("%d\n",left);
change_interval(1,1,n,1,left,left+x-1);
}
else
{
printf("0\n");
}
}
else
{
scanf("%d",&y);
change_interval(1,1,n,2,x,x+y-1);
}
}
return 0;
}

区间连续长度的线段树——洛谷P2894 [USACO08FEB]酒店Hotel的更多相关文章

  1. 洛谷 P2894 [USACO08FEB]酒店Hotel 解题报告

    P2894 [USACO08FEB]酒店Hotel 题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultur ...

  2. 洛谷P2894 [USACO08FEB]酒店Hotel

    P2894 [USACO08FEB]酒店Hotel https://www.luogu.org/problem/show?pid=2894 题目描述 The cows are journeying n ...

  3. 洛谷P2894 [USACO08FEB]酒店Hotel [线段树]

    题目传送门 酒店 题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and ...

  4. 洛谷P2894[USACO08FEB]酒店Hotel(线段树)

    问题描述 奶牛们最近的旅游计划,是到苏必利尔湖畔,享受那里的湖光山色,以及明媚的阳光.作为整个旅游的策划者和负责人,贝茜选择在湖边的一家著名的旅馆住宿.这个巨大的旅馆一共有N (1 <= N & ...

  5. 洛谷 P2894 [USACO08FEB]酒店Hotel

    题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a ...

  6. 洛谷 P2894 [USACO08FEB]酒店Hotel-线段树区间合并(判断找位置,不需要维护端点)+分治

    P2894 [USACO08FEB]酒店Hotel 题目描述 The cows are journeying north to Thunder Bay in Canada to gain cultur ...

  7. 浅谈线段树 (例题:[USACO08FEB]酒店Hotel)By cellur925

    今天我们说说线段树. 我个人还是非常欣赏这种数据结构的.(逃)因为它足够优美,有递归结构,有左子树和右子树,还有二分的思想. emm这个文章打算自用,就不写那些基本的操作了... 1° 简单的懒标记( ...

  8. 洛谷 P2894 [USACO08FEB]酒店

    题目描述 用线段树维护三个值:区间最长空位长度,从左端点可以延伸的最长空位长度,从右端点可以延伸的最长空位长度. #include<complex> #include<cstdio& ...

  9. 洛谷P2894 [USACO08FEB]酒店Hotel_区间更新_区间查询

    Code: #include<cstdio> #include<algorithm> #include<cstring> using namespace std; ...

随机推荐

  1. Vue使用指南(三)

    组件 '''1.根组件:new Vue()创建的组件,一般不明确自身的模板,模板就采用挂载点2.局部组件: local_component = {}2.全局组件: Vue.component({})' ...

  2. The 2018 ACM-ICPC Asia Nanjing Regional Programming Contest

    A. Adrien and Austin 大意: $n$个石子, 编号$1$到$n$, 两人轮流操作, 每次删除$1$到$k$个编号连续的石子, 不能操作则输, 求最后胜负情况. 删除一段后变成两堆, ...

  3. JNI创建共享内存导致JVM terminated的问题解决(segfault,shared memory,内存越界,内存泄漏,共享内存)

    此问题研究了将近一个月,最终发现由于JNI不支持C中创建共享内存而导致虚拟机无法识别这块共享内存,造成内存冲突,最终虚拟机崩溃. 注意:JNI的C部分所使用的内存也是由JVM创建并管理的,所以C创建了 ...

  4. Linux 查询端口被占用命令

    1.lsof -i:端口号 用于查看某一端口的占用情况,比如查看8000端口使用情况,lsof -i:8000 lsof -i:8080:查看8080端口占用 lsof abc.txt:显示开启文件a ...

  5. 查询慢SQL

      可以查看当前时间访问库的所有请求SQL SELECT COUNT(*) AS c,state,info  FROM `information_schema`.processlist GROUP B ...

  6. svn提交时把node_modules忽略掉

    空白处右键>选中TortoiseSVN>设置(settings)>常规设置(General)>Subversion>编辑(edit)>在弹出的config文件中找g ...

  7. S5PV210 timer

    TCFG0, R/W, Address = 0xE250_0000 Timer Input Clock Frequency = PCLK / ( {prescaler value + 1} ) / { ...

  8. XSS的类型

  9. Linux命令——logger

    参考:How to use logger on Linux Difference between /var/log/messages, /var/log/syslog, and /var/log/ke ...

  10. C++——多态实现原理分析

    前言 虚函数执行速度要稍慢一些.为了实现多态性,每一个派生类中均要保存相应虚函数的入口地址表,函数的调用机制也是间接实现.所以多态性总是要付出一定代价,但通用性是一个更高的目标. 实验环境 Windo ...