//9372104 NKHelloWorld 3667 Accepted 3740K 1000MS G++ 3738B 2011-09-29 15:06:22 //9372139 NKHelloWorld 3667 Accepted 3228K 594MS C++ 3740B 2011-09-29 15:12:45 /* 转自:http://www.cnblogs.com/superbin/archive/2010/07/18/1780194.html 题型:线段树(设计并维护复杂域) 描述:旅店登记,1.找一段最靠前的连续w个空房间;2.退订[x,x-d+1]段的房间。 思路: 1. 域的设计 struct Seg { int l, r; int lx, rx, mx; char cv; }; lx :左端连续空房间数 rx: 右端连续空房间数 mx: 连续最大空房间数 cv : = 0,全空, = 1 全满, = -1 非空非满。 2. 域的维护 开房:先用find(w, 1); 找到位置 rom, 然后用 mody(rom, rom+w-1, 0, 1); 进行插入操作 退房:进行删除操作mody(x, x-d+1, 1, 1) 因为此题区间的修改(插入和删除)很相似,所以用一个函数实现,0表示插入,1表示删除。 对cv域的维护包括 1. t[k].l == l && t[k].r == r 。 2. 根据父节点的cv值对子节点的修改(关键),find()和mody()中都需要有。 lx, rx, mx需要在回溯的过程维护:mx 为 两个子节点的mx和交叉区间和的最大值, 父节点的lx = 左子节点的lx + (右子节点的lx); 父节点的rx = 右子节点的rx + (左子节点的rx); 当左右子节点的lx,rx为整个区间长时,()需加上。 */ #include <cstdio> #include <iostream> using namespace std; #define MAXN 50010 struct SEGMENTTREE { int lt,rt,lval,rval,totval,state; }tree[4*MAXN]; int n,m; void buildsegtree(int root,int lt,int rt) { tree[root].lt = lt; tree[root].rt = rt; tree[root].lval = tree[root].rval = tree[root].totval = rt - lt + 1; tree[root].state = 0; if(lt != rt) { int mid = (lt+rt)>>1; buildsegtree(root<<1,lt,mid); buildsegtree(root<<1|1,mid+1,rt); } } void pushdown(int root) { tree[root<<1].state = tree[root<<1|1].state = tree[root].state; if(tree[root].state == 0) { tree[root<<1].lval = tree[root<<1].rval = tree[root<<1].totval = tree[root<<1].rt - tree[root<<1].lt + 1; tree[root<<1|1].lval = tree[root<<1|1].rval = tree[root<<1|1].totval = tree[root<<1|1].rt - tree[root<<1|1].lt +1; } else { tree[root<<1].lval = tree[root<<1].rval = tree[root<<1].totval = 0; tree[root<<1|1].lval = tree[root<<1|1].rval = tree[root<<1|1].totval = 0; } tree[root].state = -1; } int query(int root,int lenth) { if(tree[root].lt == tree[root].rt) { if(tree[root].state == false && lenth == 1) return tree[root].lt; return 0; } if(tree[root].state != -1) pushdown(root); if(tree[root<<1].totval >= lenth) return query(root<<1,lenth); if(tree[root<<1].rval + tree[root<<1|1].lval >= lenth) return tree[root<<1].rt - tree[root<<1].rval + 1; if(tree[root<<1|1].totval >= lenth) return query(root<<1|1,lenth); return 0; } void update(int root,int lt,int rt,int state) { //printf("root:%d lt:%d rt:%d state:%d\n",root,lt,rt,state); if(tree[root].lt == lt && tree[root].rt == rt) { tree[root].state = state; if(state==1) tree[root].lval = tree[root].rval = tree[root].totval = 0; else if(state == 0) tree[root].lval = tree[root].rval = tree[root].totval = rt - lt+ 1; return ; } if(tree[root].state != -1) pushdown(root); int mid = (tree[root].lt + tree[root].rt)>>1; if( rt <= mid ) update(root<<1,lt,rt,state); else if(lt > mid) update(root<<1|1,lt,rt,state); else { update(root<<1,lt,mid,state); update(root<<1|1,mid+1,rt,state); } tree[root].lval = tree[root<<1].lval; tree[root].rval = tree[root<<1|1].rval; tree[root].totval = max( max(tree[root<<1].totval,tree[root<<1|1].totval) , tree[root<<1].rval + tree[root<<1|1].lval); if(tree[root].lval == tree[root<<1].rt - tree[root<<1].lt + 1) tree[root].lval += tree[root<<1|1].lval; if(tree[root].rval == tree[root<<1|1].rt - tree[root<<1|1].lt +1) tree[root].rval += tree[root<<1].rval; if(tree[root<<1].state == tree[root<<1|1].state) tree[root].state = tree[root<<1].state; } void output(int root) { printf("root: %d, lt:%d rt:%d\t lval:%d rval:%d totval:%d state:%d\n",root,tree[root].lt,tree[root].rt,tree[root].lval,tree[root].rval,tree[root].totval,tree[root].state); if(tree[root].lt != tree[root].rt) { output(root<<1); output(root<<1|1); } } int main() { int i,a,b,op; scanf("%d%d",&n,&m); buildsegtree(1,1,n); while(m--) { scanf("%d",&op); if(op==1) { scanf("%d",&a); b = query(1,a); printf("%d\n",b); if(b) { update(1,b,b+a-1,1); //output(1); } } else { scanf("%d%d",&a,&b); update(1,a,a+b-1,0); //output(1); } } return 0; }