/* * File: main.cpp * Author: Mi *关于这个题其实以前也做过一次这个题,但还有有些地方没有弄懂 * 这次又重新拿出来认真看了下,终于搞懂了,对线段树的认识有加深了一步 * 题目意思就不说了 * 分别用lv,rv,cv来表示线段左边剩余的房间数,右边剩余的房间,总共剩余的房间数 * state(0,1,-1)分别表示,没有人住,已经有人住,和其它情况(也就是说这条线段有一部分有人住,一部分没人住) * 比如11000111这么一条线段,1表示有人,则lv=2,rv=3,cv=3 * 这个题在查找的时候没有什么,就和普通的线段树一样的查找 * 在判断的时候先判断左边T[root<<1].cv>=l?如果不在判断中间即:T[root<<1].rv+T[root<<1|1].lv>=l? * 最后判断右边:T[root<<1|1].cv>=l? * 如果都不满足则住不下,返回0 * 在更新时要注意lv,rv,cv的修改,其实自己去画一画很容易就能明白 * T[root].lv=T[root<<1].lv,T[root].rv=T[root<<1|1].rv * T[root].cv=max(max(T[root<<1].cv,T[root<<1|1].cv),T[root<<1].rv+T[root<<1|1].lv) * 还有就是有种特殊情况要处理,就是如果T[root].lv==T[root<<1].r-T[root].l+1 * 则T[root].lv+=T[root<<1|1].lv * 其实很容易明白,root的lv等于root<<|1的总长度,那么就说明了,root的lv和root的rv是接触了的 * 举个例子:线段:11101,(T[root].l=1,T[root].r=5)则T[root].lv=4,T[root].rv=0,T[root].cv=3 * 左子树:111(T[root<<1].l=1,T[root<<1].r=3) T[root<<1].lv=3,T[root<<1].rv=3,T[root<<1].cv=3 * 右子树:01 (T[root.<<1|1].l=4,T[root<<1|1].r=5) T[root<<1|1].lv=0,T[root<<1|1].rv=1,T[root<<1].cv=1 * 这么举例应该很容易看明白刚才为什么要特殊处理了吧?其实画一画就想通了,对T[root].rv的处理方法相同 * Created on 2011年3月13日, 下午2:24 */ #include <cstdlib> #include <stdio.h> #include <string.h> #define N 50005 #define max(a,b) ((a)>(b))?(a):(b) /* * */ int ans; struct tree { int l,r,lv,rv,cv,state; }T[N*3]; void init(int i) { T[i].lv=T[i].rv=T[i].cv=T[i].state?0:(T[i].r-T[i].l+1); return ; } void build(int l,int r,int root) { T[root].l=l,T[root].r=r; T[root].state=root==1?0:-1; if(l==r) return ; int mid=(l+r)>>1; build(l,mid,root<<1); build(mid+1,r,root<<1|1); } void modify(int l,int r,int root,int d) { if(l<=T[root].l&&r>=T[root].r) { T[root].state=d; init(root); return ; } if(T[root].state!=-1) { T[root<<1].state=T[root<<1|1].state=T[root].state; init(root<<1); init(root<<1|1); T[root].state=-1; } int mid=(T[root].l+T[root].r)>>1; if(l<=mid) modify(l,r,root<<1,d); if(r>=mid+1) modify(l,r,root<<1|1,d); T[root].lv=T[root<<1].lv; T[root].rv=T[root<<1|1].rv; T[root].cv=max(max(T[root<<1].cv,T[root<<1|1].cv),T[root<<1].rv+T[root<<1|1].lv); if(T[root].lv==T[root<<1].r-T[root<<1].l+1) T[root].lv+=T[root<<1|1].lv; if(T[root].rv==T[root<<1|1].r-T[root<<1|1].l+1) T[root].rv+=T[root<<1].rv; } int query(int l,int root) { if(T[root].r-T[root].l+1==1) return T[root].l; if(T[root].state!=-1) { T[root<<1].state=T[root<<1|1].state=T[root].state; init(root<<1); init(root<<1|1); T[root].state=-1; } if(T[root<<1].cv>=l) return query(l,root<<1); else if(T[root<<1].rv+T[root<<1|1].lv>=l) return T[root<<1].r-T[root<<1].rv+1; else if(T[root<<1|1].cv>=l) return query(l,root<<1|1); return 0; } int main(int argc, char** argv) { int n,q; scanf("%d%d",&n,&q); build(1,n,1); while(q--) { int a,b,t; scanf("%d",&t); if(t==1) { scanf("%d",&a); b=query(a,1); printf("%d/n",b); if(b) modify(b,a+b-1,1,1); } else { scanf("%d%d",&a,&b); modify(a,a+b-1,1,0); } } return 0; }