Hotel
Time Limit: 3000MS | Memory Limit: 65536K |
如果看 WA 法:请向下翻至 PS:
题意:
你是导游哦 ~ 给你 n 间房间, 以及 m 个请求
opr = 1 时,输入 x ,表示需要 连续 x 个房间
有房间则 输出 房间开始的编号(要求尽量小),并占用,没有房间 输出 0
opr = 2 时,输入 x, y 表示从 x 号房间起 , 连续 y 个房间 解除占用。
分析:
首先:连续区间操作 -> 线段树
其次: 你需要会 区间 合并 操作 (为什么呢?) 不过,区间合并是一个简单的东西 -_-
(别看老师或者网上说的 玄乎其玄 不能有心理压力)
那究竟为什么呢?
回去看题目——我们对房间 解除占用 √ 很OK,普通的 区间修改 问题(因为有区间修改,lazy 标记闪亮登场)
那当 opr = 1 时,我们 需要 找到 首个连续长度为 x 的区间 ,并且占用,怎么办呢?
分成两步 : 1. 找到区间开始的位置
2. 占用 [ pos , pos+x-1 ] 区间 (区间修改,Easy) √
然后:问题只剩下 找 连续区间 的初始位置 (别急)
1. 判断 当前区间 是否有 满足条件 的 连续区间 用 maxn 记录最长连续区间
连续区间可能有如下几种情况:
为了更新 maxn ,我们要存下 节点从左边开始最长连续区间 llen 从右边开始最长连续区间 rlen
对于 当前节点 a 的 llen ,rlen 从他儿子那更新:
int lson(a<<1), rson(a<<1|1);
tre[a].llen = tre[lson].llen;
if (tre[lson].llen == tre[lson].len) tre[a].llen = tre[lson].len+tre[rson].llen;
tre[a].rlen = tre[rson].rlen;
if (tre[rson].rlen == tre[rson].len) tre[a].rlen = tre[rson].len+tre[lson].rlen;
tre[a].maxn = max(tre[lson].maxn,max(tre[rson].maxn, tre[lson].rlen+tre[rson].llen));
① a 节点的 llen = 左儿子 的 llen
② 如果 左儿子 的 llen = 左区间 长度 ,说明 a 节点 的 llen 可以延伸至 右儿子, 那就加上 右儿子的 llen
详见图(SS 1);
同理可得 rlen
a节点 maxn的更新: 【区间合并】
① 左儿子 的 maxn
② 右儿子 的 maxn
③ 左儿子的 rlen (从右边开始最长连续区间 ) + 右儿子的 llen (从左边开始最长连续区间)
三者取 max KO!
也许你并没有知道整道题的做法,但是你知道了区间合并之后,请尝试着自己理思路,然后豁然开朗!
lazy 标记 一共三种状态(当然一个变量就好了) -1 : 未进行区间操作 0:清空 1:有人
你还需要看下面一段代码: a 是当前节点 wid是查找的连续房间数
int get_ans (int a,int wid){
int mid(tre[a].l + tre[a].r>>1), lson(a<<1), rson(a<<1|1);// int t() ; 等同于 int t= ;
if (tre[a].lzy1!=-1) xia_fang(a);//lazy
if (tre[a].maxn<wid) return 0;
if (tre[a].l == tre[a].r) return tre[a].l;
if (tre[lson].maxn>=wid) return get_ans(lson,wid);
else if (tre[lson].rlen + tre[rson].llen >= wid) return mid-tre[lson].rlen+1;
else return get_ans(rson,wid);
}
PS:
如果你 WA 了,请注意以下问题:
① 如果 返回位置的 答案 是 0 ,注意输出后跳出,不能进行 区间修改 (容易忽略的)
②(写法的不同)需要判断 opr=2 时 输入的连续长度 y 可能为 0
在我的代码中:
int x = wread(), y = wread(); if (x+y-1 < x) continue;// fnd_qu_0(1, x, x+y-1); //区间置0
③不同的 OJ 上有的是多组数据,有的是单组数据,请注意
数据①:
23 3
1 12
1 20
1 11
AC: 1
0
13
数据② :
尊重原作者,链接
附上AC代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
inline void wprint (int x){
if (x>9) wprint(x/10);
putchar (x%10+'0');
}
inline void print (int x){
if (x<0) x=-x,putchar('-');
wprint(x);
putchar('\n');
}
inline int wread(){
char c(getchar());int wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar();}
while (c>='0' && c<='9'){wans=wans*10+c-'0'; c=getchar();}
return wans*=flag;
}
struct node{int l,r,maxn,llen,rlen,len,lzy1;}tre[400006];
int n,m;
int fnd_max_3 (int a,int b,int c){
int max_num=a;
if (b>a) max_num=b;
if (c>max_num) max_num=c;
return max_num;
}
void make_tre (int a,int l,int r){
tre[a].l=l; tre[a].r=r; tre[a].llen=0; tre[a].rlen=0; tre[a].lzy1=-1; tre[a].maxn=0; tre[a].len=0;
if (l==r){tre[a].len = tre[a].maxn = tre[a].llen = tre[a].rlen=1; return ;}
int mid(l+r>>1), lson(a<<1), rson(a<<1|1);
make_tre(lson, l, mid);
make_tre(rson, mid+1, r);
tre[a].len = tre[lson].len + tre[rson].len;
tre[a].llen = tre[a].rlen = tre[a].maxn = tre[a].len;
}
void xia_fang (int a){
int lson(a<<1), rson(a<<1|1);
if (tre[a].lzy1==1){
tre[lson].lzy1=1; tre[rson].lzy1=1;
tre[lson].rlen=tre[lson].llen=tre[lson].maxn=0;
tre[rson].rlen=tre[rson].llen=tre[rson].maxn=0;
}
else {
tre[lson].lzy1=0; tre[rson].lzy1=0;
tre[lson].rlen=tre[lson].llen=tre[lson].maxn=tre[lson].len;
tre[rson].rlen=tre[rson].llen=tre[rson].maxn=tre[rson].len;
}
tre[a].lzy1=-1;
}
void push_up (int a){
int lson(a<<1), rson(a<<1|1);
tre[a].llen = tre[lson].llen;
if (tre[lson].llen == tre[lson].len) tre[a].llen = tre[lson].len+tre[rson].llen;
tre[a].rlen = tre[rson].rlen;
if (tre[rson].rlen == tre[rson].len) tre[a].rlen = tre[rson].len+tre[lson].rlen;
tre[a].maxn = max(tre[lson].maxn,max(tre[rson].maxn, tre[lson].rlen+tre[rson].llen));
}
int get_ans (int a,int wid){
int mid(tre[a].l + tre[a].r>>1), lson(a<<1), rson(a<<1|1);
if (tre[a].lzy1!=-1) xia_fang(a);
if (tre[a].maxn<wid) return 0;
if (tre[a].l == tre[a].r) return tre[a].l;
if (tre[lson].maxn>=wid) return get_ans(lson,wid);
else if (tre[lson].rlen + tre[rson].llen >= wid) return mid-tre[lson].rlen+1;
else return get_ans(rson,wid);
}
void fnd_qu_0 (int a,int l,int r){
if (tre[a].l>=l && tre[a].r<=r){
tre[a].llen=tre[a].rlen=tre[a].maxn=tre[a].len;
tre[a].lzy1=0;return ;
}
if (tre[a].lzy1!=-1) xia_fang(a);
int mid(tre[a].l + tre[a].r>>1), lson(a<<1), rson(a<<1|1);
if (r<=mid) fnd_qu_0(lson,l,r);
else if (l>mid) fnd_qu_0(rson,l,r);
else fnd_qu_0(lson,l,r),fnd_qu_0(rson,l,r);
//
push_up (a);
}
void fnd_qu_1(int a,int l,int r){
if (tre[a].l>=l && tre[a].r<=r) {
tre[a].llen=tre[a].rlen=tre[a].maxn=0;
tre[a].lzy1=1; return ;
}
if (tre[a].lzy1!=-1) xia_fang(a);
int mid(tre[a].l+tre[a].r>>1), lson(a<<1), rson(a<<1|1);
if (r<=mid) fnd_qu_1(lson,l,r);
else if (l>mid) fnd_qu_1(rson,l,r);
else fnd_qu_1(lson,l,r),fnd_qu_1(rson,l,r);
//
push_up (a);
}
int main (){
while (~scanf ("%d%d",&n,&m)){
make_tre(1,1,n);
while (m--){
int opr(wread());
if (opr==1){
int wid(wread());
int pos(get_ans(1,wid));
print(pos);
if (pos)
fnd_qu_1(1,pos,pos+wid-1);
}
else{
int x(wread()), y(wread());
if (x+y-1<x) continue;
fnd_qu_0(1,x,x+y-1);
}
}
}
return 0;
}