您的位置:首页 > 其它

poj3667 hotel(线段树区间合并)

2012-10-18 13:35 399 查看
http://poj.org/problem?id=3667

之前网络赛水过一道区间合并的题 当时是全靠运气试对的 。

昨天纠结了一晚上也没看出来哪错,改的都跟人家代码一样了还是不对,今天又重新敲了一遍,莫名的就对了,,

开两个数组分别存这个区间两端点的连续区间 再开一标记数组 用来更新 向上向下都要更新

View Code

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 50010
int s[N<<2],kc[N<<2],lc[N<<2],rc[N<<2];
void build(int l,int r,int w)
{
s[w] = lc[w] = rc[w] = r-l+1;
kc[w] = -1;
if(l==r)
return ;
int m = (l+r)/2;
build(l,m,w<<1);
build(m+1,r,w<<1|1);
}
void pushdown(int w,int c)
{
if(kc[w]!=-1)
{
kc[w<<1] = kc[w<<1|1] = kc[w];
s[w<<1] = lc[w<<1] = rc[w<<1] = kc[w]?0:c-(c>>1);
s[w<<1|1] = lc[w<<1|1] = rc[w<<1|1] = kc[w]?0:c>>1;
kc[w] = -1;
}
}
void pushup(int w,int c)
{
lc[w] = lc[w<<1];
rc[w] = rc[w<<1|1];
if(lc[w]==c-(c>>1))
lc[w]+=lc[w<<1|1];
if(rc[w]==c>>1)
rc[w]+=rc[w<<1];
s[w] = max(rc[w<<1]+lc[w<<1|1],max(s[w<<1],s[w<<1|1]));//找出区间中最长的连续段
}
void update(int a,int b,int c,int l,int r,int w)
{
if(l>=a&&b>=r)
{
s[w] = lc[w] = rc[w] = c?0:r-l+1;
kc[w] = c;
return ;
}
pushdown(w,r-l+1);
int m = (l+r)>>1;
if(a<=m)
update(a,b,c,l,m,w<<1);
if(b>m)
update(a,b,c,m+1,r,w<<1|1);
pushup(w,r-l+1);
}
int query(int c,int l,int r,int w)
{
if(l==r)
return l;
pushdown(w,r-l+1);
int m = (l+r)>>1;
if(s[w<<1]>=c)
return query(c,l,m,w<<1);
else
if(rc[w<<1]+lc[w<<1|1]>=c)//中间段
return m-rc[w<<1]+1;
return query(c,m+1,r,w<<1|1);
}
int main()
{
int i,j,k,n,m,x,d;
cin>>n>>m;
build(1,n,1);
while(m--)
{
cin>>k;
if(k==1)
{
cin>>x;
if(s[1]<x)
printf("0\n");
else
{
int p = query(x,1,n,1);
cout<<p<<endl;
update(p,p+x-1,1,1,n,1);//将这一段更新为已被占
}
}
else
{
cin>>x>>d;
update(x,x+d-1,0,1,n,1);//将这一段更新为空
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: