感想:
没有什么说的了。。。。。越做线段树越感觉自己水。。。。。。。。这个我感觉自己就真坑了大家了。。。。。。。难的不会,简单的也水不过了。。。。。哎,最近这是什么情况啊!!!
/* 题目:http://poj.org/problem?id=3667 题意:旅馆有编号为1~n的房间,现在可能有m波人过了租房, 每波人可能要定连续的d间房,如果有的话,编号尽量小,没有的话就说0, 也可能有d个人要退房,他们的房是连续的x~x+d-1这几间。。。 分析:这题属于线段树区间合并,还是比较简单的。。。 首先,当然要记录一个区间最长的连续值了,这个方便取值, 然后要考虑一个区间如何从它的两子区间转移过来,这个最长的值肯定可以使连个值区间最长值的大者, 当然,两子区间合并,可能得到更长的,而这个更长的肯定在中间, 我们需要记录左子区间从右端开始到左端的最长连续值,记录右子区间从左端到右端的最长连续值, 新的值就是这两个值相加了,当然,由于不确定哪个区间是左区间,所以每个区间都要记录这三个值 */ #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn=50002; #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r int col[maxn<<2],lmax[maxn<<2],rmax[maxn<<2],mmax[maxn<<2],q,n,m; void pushup(int rt,int l,int r) { int mid=(l+r)>>1; mmax[rt]=max(mmax[rt<<1],mmax[rt<<1|1]); lmax[rt]=lmax[rt<<1]; rmax[rt]=rmax[rt<<1|1]; if(lmax[rt<<1]==mid-l+1) lmax[rt]+=lmax[rt<<1|1]; if(rmax[rt<<1|1]==r-mid) rmax[rt]+=rmax[rt<<1]; mmax[rt]=max(mmax[rt],lmax[rt<<1|1]+rmax[rt<<1]); } void pushdown(int rt,int l,int r) { if(col[rt]!=-1) { int mid=(l+r)>>1; col[rt<<1]=col[rt<<1|1]=col[rt]; if(col[rt]==1) { lmax[rt<<1]=rmax[rt<<1]=mmax[rt<<1]=rmax[rt<<1|1]=lmax[rt<<1|1]=mmax[rt<<1|1]=0; } else { lmax[rt<<1]=rmax[rt<<1]=mmax[rt<<1]=mid-l+1; lmax[rt<<1|1]=rmax[rt<<1|1]=mmax[rt<<1|1]=r-mid; } col[rt]=-1; } } void build(int rt,int l,int r) { lmax[rt]=rmax[rt]=mmax[rt]=r-l+1; col[rt]=-1;///未被覆盖 if(l==r) { return; } int mid=(l+r)>>1; build(lson); build(rson); //pushup(rt,l,r); } void updata(int rt,int l,int r,int L,int R,int val) { if(L<=l&&r<=R) { col[rt]=val; lmax[rt]=rmax[rt]=mmax[rt]=(val?0:r-l+1); return; } pushdown(rt,l,r); int mid=(l+r)>>1; if(mid>=L) updata(lson,L,R,val); if(mid<R) updata(rson,L,R,val); pushup(rt,l,r); } int query(int rt,int l,int r,int sum) { if(mmax[rt]<sum)return 0; if(lmax[rt]>=sum) return l; pushdown(rt,l,r); int mid=(l+r)>>1; if(mmax[rt<<1]>=sum)return query(lson,sum); if(rmax[rt<<1]+lmax[rt<<1|1]>=sum) return mid-rmax[rt<<1]+1; return query(rson,sum); } int main() { int a,b,sum; while(scanf("%d%d",&n,&m)!=EOF) { build(1,1,n); for(int i=1; i<=m; i++) { scanf("%d",&q); if(q==1) { scanf("%d",&sum); int ret=query(1,1,n,sum); printf("%d\n",ret); if(ret) updata(1,1,n,ret,ret+sum-1,1);///已经利用 } else { scanf("%d%d",&a,&b); b=a+b-1; updata(1,1,n,a,b,0);///重新获得空间 } } } return 0; }