POJ
来源:互联网 发布:联赢软件 编辑:程序博客网 时间:2024/06/03 14:36
点我看题
题意:有L个连续的房间,日常会有一些人登记入住,也会有一些人退房,一次登记入住和一次退房都是连续的,问每次登记入住时,是否有连续的房间提供给入住者们,有的话,求入住的第一个房间序号.
分析:裸的线段树区间合并加查询,入住的时候,查询是否有满足条件的房间(st[1].sum>=所需要的房间数就是满足条件了),然后更新线段树,退房的话就更简单了,直接更新结点的长度就好.
参考代码:
/*区间合并*/#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#include<iostream>using namespace std;#define lson rt<<1#define rson rt<<1|1const int maxn = 5e4+10;int n,q;struct SegTree{ int l,r; int sum;//当前结点保存的可入住人数的值 int lsum,rsum;//当前结点 int tag;//tag=1代表入住,-1代表退房,0代表不进行操作};SegTree st[maxn<<2];//向上更新void PushUp( int rt){ st[rt].lsum = st[lson].lsum; st[rt].rsum = st[rson].rsum; int mid = (st[rt].l+st[rt].r)>>1; if( st[rt].lsum == mid-st[rt].l+1) st[rt].lsum += st[rson].lsum; if( st[rt].rsum == st[rt].r-mid) st[rt].rsum += st[lson].rsum; st[rt].sum = max(max(st[lson].sum,st[rson].sum),st[lson].rsum+st[rson].lsum);}//建树void Build( int l, int r, int rt){ st[rt].l = l; st[rt].r = r; st[rt].sum = r-l+1; st[rt].lsum = r-l+1; st[rt].rsum = r-l+1; st[rt].tag = 0; if( l == r) return; int mid = (l+r)>>1; Build(l,mid,lson); Build(mid+1,r,rson);// PushUp(rt);//这里不需要往上更新}//向下更新void PushDown( int rt){ if( st[rt].tag != 0) { st[lson].tag = st[rson].tag = st[rt].tag; if( st[rt].tag == 1) { st[lson].sum = st[lson].lsum = st[lson].rsum = 0; st[rson].sum = st[rson].lsum = st[rson].rsum = 0; } else if( st[rt].tag == -1) { st[lson].sum = st[lson].lsum = st[lson].rsum = st[lson].r-st[lson].l+1; st[rson].sum = st[rson].lsum = st[rson].rsum = st[rson].r-st[rson].l+1; } st[rt].tag = 0; }}//区间查询//查询有没有区间长度至少为len的区间//个人认为这里的l和r都可以通过rt得到,但是为了书写方便,还是给加上去了int Query( int l, int r, int rt, int len){ if( l == r) return l; PushDown(rt);//继续向下更新查找 int mid = (l+r)>>1; if( st[lson].sum >= len) return Query(l,mid,lson,len); else if( st[lson].rsum+st[rson].lsum >= len) return mid-st[lson].rsum+1; else return Query(mid+1,r,rson,len);}//区间合并void Update( int L, int R, int rt, int tag){ if( st[rt].l == L && st[rt].r == R) { st[rt].tag = tag; if( tag == 1) st[rt].sum = st[rt].lsum = st[rt].rsum = 0; else if( tag == -1) st[rt].sum = st[rt].lsum = st[rt].rsum = st[rt].r-st[rt].l+1; return; } PushDown(rt);//向下更新 int mid = (st[rt].l+st[rt].r)>>1; if( R <= mid) Update(L,R,lson,tag); else if( L > mid) Update(L,R,rson,tag); else { Update(L,mid,lson,tag); Update(mid+1,R,rson,tag); } PushUp(rt);//向上更新}int main(){ while( ~scanf("%d%d",&n,&q)) { Build(1,n,1); while( q--) { int op; int x,y; scanf("%d",&op); if( op == 1) { scanf("%d",&x); if( x <= st[1].sum) { int pos = Query(1,n,1,x); printf("%d\n",pos); //pos和pos+x-1分别表示更新的起始和结束的位置 //第一个1为根结点,第二个1为tag标记 Update(pos,pos+x-1,1,1); } else puts("0"); } else if( op == 2) { scanf("%d%d",&x,&y); //参数意义同上 Update(x,x+y-1,1,-1); } } } return 0;}
阅读全文
0 0
- POJ
- poj
- POJ
- POJ
- poj
- poj
- POJ
- POJ
- poj
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- POJ
- 1000
- hdu 6050 Funny Function(快速幂)
- 欢迎使用CSDN-个人第一个CSDN博客
- 1091. Acute Stroke (30)三维广搜
- Birthday Paradox(生日悖论)
- POJ
- 用for循环打印菱形
- bzoj3517: 翻硬币
- [LeetCode] 111. Minimum Depth of Binary Tree
- 幸福的道路(race)
- OpenCL tutorial
- Python学习笔记——分支循环
- 并行算法设计--Foster的设计方法论
- 异常提示