【线段树】 POJ 3667 Hotel

这道题和那道HDOJ 3308 LCIS比较像。。那道题目我就写了超久,当时是不确定保存什么信息。。这道题也写了很久,主要是各种低级错误,找错找了很久,超级火。。。。


#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <climits>
#define maxn 200005
#define eps 1e-6
#define mod 1000000007
#define INF 99999999
#define lowbit(x) (x&(-x))
typedef long long LL;
using namespace std;

int lnum[maxn], rnum[maxn], segnum[maxn];
int lmax[maxn], rmax[maxn];
int segmax[maxn], mark[maxn];
int n, m, k, ok, ans;
int ql, qr, cnt;

void build(int o, int L, int R)
{
	lnum[o]=segnum[o]=L, rnum[o]=R;
	lmax[o]=rmax[o]=segmax[o]=R-L+1;
	mark[o]=0;
	if(L==R) return;
	int mid=(L+R)>>1;
	build(o<<1, L, mid);
	build(o<<1 | 1, mid+1, R);
}
void pushdown(int o, int L, int R)
{
	int mid=(R+L)>>1;
	lnum[o<<1]=segnum[o]=L, rnum[o<<1]=mid;
	lnum[o<<1 | 1]=mid+1, rnum[o<<1 | 1]=R;
	lmax[o<<1]=rmax[o<<1]=segmax[o<<1]=mid-L+1;
	lmax[o<<1 | 1]=rmax[o<<1 | 1]=segmax[o<<1 | 1]=R-mid;
	mark[o<<1]=mark[o<<1 | 1]=1;
	mark[o]=0;
}
void _pushdown(int o, int L, int R)
{
	int mid=(R+L)>>1;
	lnum[o<<1]=segnum[o]=L, rnum[o<<1]=mid;
	lnum[o<<1 | 1]=mid+1, rnum[o<<1 | 1]=R;
	lmax[o<<1]=rmax[o<<1]=segmax[o<<1]=0;
	lmax[o<<1 | 1]=rmax[o<<1 | 1]=segmax[o<<1 | 1]=0;
	mark[o<<1]=mark[o<<1 | 1]=2;
	mark[o]=0;
}
void pushup(int o, int L, int R)
{
	int tmp=0;
	if(rmax[o<<1] && lmax[o<<1 | 1]) tmp=rmax[o<<1]+lmax[o<<1 | 1];
	lnum[o]=lnum[o<<1], rnum[o]=rnum[o<<1 | 1];
	if(tmp>=segmax[o<<1] && tmp>=segmax[o<<1 | 1]) segmax[o]=tmp, segnum[o]=rnum[o<<1]-rmax[o<<1]+1;
	else if(segmax[o<<1]>segmax[o<<1 | 1]) segmax[o]=segmax[o<<1], segnum[o]=segnum[o<<1];
	else segmax[o]=segmax[o<<1 | 1], segnum[o]=segnum[o<<1 | 1];
	if(lnum[o]==segnum[o]) lmax[o]=segmax[o];
	else lmax[o]=lmax[o<<1];
	if(rnum[o]==segmax[o]+segnum[o]-1) rmax[o]=segmax[o];
	else rmax[o]=rmax[o<<1 | 1];
}
void updata(int o, int L, int R)
{
	if(ql<=L && qr>=R){
		if(k==1){
			lnum[o]=segnum[o]=L, rnum[o]=R;
			lmax[o]=rmax[o]=segmax[o]=R-L+1;
			mark[o]=1;
		}
		else{
			lnum[o]=segnum[o]=L, rnum[o]=R;
			lmax[o]=rmax[o]=segmax[o]=0;
			mark[o]=2;
		}
		return;
	}
	if(mark[o]==1) pushdown(o, L, R);
	if(mark[o]==2) _pushdown(o, L, R);
	int mid=(R+L)>>1;
	if(ql<=mid) updata(o<<1, L, mid);
	if(qr>mid) updata(o<<1 | 1, mid+1, R);
	pushup(o, L, R);
}
void query(int o, int L, int R)
{
	if(ok) return;
	if(segmax[o]<cnt) return;
	if(L==R){
		ans=L, ok=1;
		return;
	}
	int mid=(R+L)/2;
	if(segmax[o<<1]>=cnt) query(o<<1, L, mid);
	if(ok) return;
	if(rmax[o<<1]+lmax[o<<1 | 1]>=cnt) ans=rnum[o<<1]-rmax[o<<1]+1, ok=1;
	if(ok) return;
	if(segmax[o<<1 | 1]>=cnt) query(o<<1 | 1, mid+1, R);
	if(ok) return;
	ans=segnum[o], ok=1;
}
void solve(void)
{
	int kk;
	while(m--){
		scanf("%d",&kk);
		if(kk==1){
			k=2, ok=0;
			scanf("%d",&cnt);
			query(1, 1, n);
			if(ok){
				printf("%d\n", ans);
				ql=ans, qr=ans+cnt-1;
				updata(1, 1, n);
			}
			else printf("0\n");
			/*
			if(segmax[1]>=cnt){
				printf("%d\n", segnum[1]);
				ql=segnum[1], qr=segnum[1]+cnt-1;
				updata(1, 1, n);
			}
			else printf("0\n");
			*/
		}
		else{
			scanf("%d%d",&ql,&qr);
			qr+=ql-1;
			k=1;
			updata(1, 1, n);
		}
	}
}
int main(void)
{
	while(scanf("%d%d",&n,&m)!=EOF){
		build(1, 1, n);
		solve();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值