您的位置:首页 > 其它

poj3667---Hotel 线段树区间合并,区间更新

2014-09-28 16:39 288 查看
题意:有N个房间,M次操作。有两种操作(1)"1 a",表示找到连续的长度为a的空房间,如果有多解,优先左边的,即表示入住。(2)"2 b len",把起点为b长度的len的房间清空,即退房。三个数组分别记录 lsum区间左值 rsum区间右值 sum区间最大值。

#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <cctype>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
template <class T>
inline bool scan_d(T &ret)
{
char c;
int sgn;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
ret*=sgn;
return 1;
}

const int maxn = 5e4+10;
int lv[maxn<<2],rv[maxn<<2], setv[maxn<<2];          //lv,rv数组可有可无,lsum rsum数组已经包含了他们的意义。
int lsum[maxn<<2],rsum[maxn<<2],sum[maxn<<2];

void push_up(int l,int r,int pos)
{
lv[pos] = lv[pos<<1];
rv[pos] = rv[pos<<1|1];
lsum[pos] = lsum[pos<<1];
rsum[pos] = rsum[pos<<1|1];
sum[pos] = max(sum[pos<<1],sum[pos<<1|1]);
sum[pos] = max(sum[pos],rsum[pos<<1]+lsum[pos<<1|1]);
int mid = (l + r) >> 1;
if (rv[pos<<1] ==lv[pos<<1|1] && !rv[pos<<1])
{
if (lsum[pos<<1] == mid - l + 1)
lsum[pos] += lsum[pos<<1|1];
if (rsum[pos<<1|1] == r - mid)
rsum[pos] += rsum[pos<<1];
sum[pos] = max(sum[pos],rsum[pos<<1]+lsum[pos<<1|1]);
}
}

void push_down(int l,int r,int pos)
{
if (~setv[pos])
{
int mid = (l + r) >> 1;
setv[pos<<1] = setv[pos<<1|1] = setv[pos];
lv[pos<<1] = setv[pos];
lv[pos<<1|1] = setv[pos];
rv[pos<<1] = setv[pos];
rv[pos<<1|1] = setv[pos];
lsum[pos<<1] = (setv[pos] ? 0 : (mid-l+1));
rsum[pos<<1] = (setv[pos] ? 0 : (mid-l+1));
lsum[pos<<1|1] = (setv[pos] ? 0 : (r-mid));
rsum[pos<<1|1] = (setv[pos] ? 0 : (r-mid));
sum[pos<<1] = (setv[pos] ? 0 : (mid-l+1));
sum[pos<<1|1] = (setv[pos] ? 0 : (r-mid));
setv[pos] = -1;
}
}

void build (int l,int r,int pos)
{
if (l == r)
{
rv[pos] = lv[pos] = 0;
sum[pos] = lsum[pos] = rsum[pos] = 1;
return;
}
int mid = (l + r) >> 1;
build(l,mid,pos<<1);
build(mid+1,r,pos<<1|1);
push_up(l,r,pos);
}

void update(int l,int r,int pos,int ua,int ub,int val)
{
if (ua <= l && ub >= r)
{
setv[pos] = val;
lv[pos] = val;
rv[pos] = val;
lsum[pos] = (val ? 0 : (r-l+1));
rsum[pos] = (val ? 0 : (r-l+1));
sum[pos] =  (val ? 0 : (r-l+1));
return;
}
int mid = (l + r) >> 1;
push_down(l,r,pos);
if (ua <= mid)
update(l,mid,pos<<1,ua,ub,val);
if (ub > mid)
update(mid+1,r,pos<<1|1,ua,ub,val);
push_up(l,r,pos);
}

int query(int l,int r,int pos,int x)
{
if (lsum[pos] >= x)
{
return l;

}
int mid = (l + r) >> 1;
push_down(l,r,pos);
if (sum[pos<<1] >= x)
return query(l,mid,pos<<1,x);
/*else if (rsum[pos<<1]&&rsum[pos<<1] + lsum[pos<<1|1] >= x)          //注释部分是错误的,,看起来很像但是不一样的
return query(l,mid,pos<<1,rsum[pos<<1]);*/
else if (rsum[pos<<1] + lsum[pos<<1|1] >= x)
return mid+1-rsum[pos<<1];
else
return query(mid+1,r,pos<<1|1,x);
}

int main(void)
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n,q;
while (~scanf ("%d%d",&n,&q))
{
build(1,n,1);
memset(setv,-1,sizeof(setv));
for (int i = 0; i < q; i++)
{
int op,x,y;
scanf ("%d",&op);
if (op == 1)
{
scanf ("%d",&x);
if (sum[1] < x)
{
printf("0\n");
continue;
}
int p = query(1,n,1,x);
printf("%d\n",p);
update(1,n,1,p,p+x-1,1);
}
else
{
scanf ("%d%d",&x,&y);
update(1,n,1,x,y+x-1,0);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: