poj3667线段树
来源:互联网 发布:初学者怎么制作软件 编辑:程序博客网 时间:2024/05/23 15:01
题意:输入n,m; n代表1-n的区间,m代表有m个操作。对于每个操作如果先输入1,则输入w,找到区间最左边未被占用的连续长度为w的区间,返回左端点,并把这段区间标记为已被占用。如果整个区间没有找到符合条件的区间。则返回0。如果输入为2,则将这段区间标记为未被占用。
解法:维护3个变量sum,lsum,rsum,sum代表的是这段区间最大连续区间的长度。lsum是从这个区间第一个元素开始连续未被占用的区间的长度,rsum是当前区间最右端开始连续未被占用的区间长度。对于每次查询,如果sum<w直接返回0。从第一段区间开始如果他的左儿子的最大连续未被占用区间的长度大于w,则查询左子树。否则如果左儿子的rsum+右儿子的lsum>=w,则返回左子树从右往左最后一个未被用占用的点。否则查询右子树。查询完后更新,更新的时候如果cover标记为1则覆盖,cover标记为0则清空。注意写法。
#include <iostream>#include <cstdio>#include <algorithm>#define N 100005using namespace std;struct node{ int l,r,lz; int sum,lsum,rsum; int cover; //cover=-1没有标记 cover=0清零操作 cover=1覆盖操作}a[N<<2];void pushdown(int k){ int m=a[k].r-a[k].l+1; if(a[k].cover!=-1){ a[k<<1].cover=a[k].cover; a[k<<1|1].cover=a[k].cover; if(a[k].cover==0){ a[k<<1].lsum=a[k<<1].rsum=a[k<<1].sum=m-(m>>1); a[k<<1|1].lsum=a[k<<1|1].rsum=a[k<<1|1].sum=m>>1; } else{ a[k<<1].lsum=a[k<<1].rsum=a[k<<1].sum=0; a[k<<1|1].lsum=a[k<<1|1].rsum=a[k<<1|1].sum=0; } a[k].cover=-1; }}void pushup(int k){ int m=a[k].r-a[k].l+1; a[k].lsum=a[k<<1].lsum; a[k].rsum=a[k<<1|1].rsum; if(a[k].lsum==m-(m>>1)) a[k].lsum+=a[k<<1|1].lsum; if(a[k].rsum==(m>>1)) a[k].rsum+=a[k<<1].rsum; a[k].sum=max(a[k<<1|1].lsum+a[k<<1].rsum,max(a[k<<1].sum,a[k<<1|1].sum));}void build(int l,int r,int k){ a[k].l=l,a[k].r=r,a[k].sum=a[k].lsum=a[k].rsum=(r-l+1); a[k].cover=-1; if(l==r){ return ; } else{ int mid=(l+r)>>1; build(l,mid,k<<1); build(mid+1,r,k<<1|1); }}int query(int l,int r,int w,int k){ if(l==r){ return l; } else{ pushdown(k); int mid=(l+r)>>1; if(a[k<<1].sum>=w){ return query(l,mid,w,k<<1); } else if(a[k<<1].rsum+a[k<<1|1].lsum>=w){ return mid-a[k<<1].rsum+1; } else{ return query(mid+1,r,w,k<<1|1); } }}void update(int l,int r,int co,int k){ if(a[k].l==l && a[k].r==r){ a[k].cover=co; if(co){ a[k].sum=a[k].lsum=a[k].rsum=0; } else{ a[k].sum=a[k].lsum=a[k].rsum=a[k].r-a[k].l+1; } return ; } else{ pushdown(k); int mid=(a[k].l+a[k].r)>>1; if(mid>=r){ update(l,r,co,k<<1); } else if(mid<l){ update(l,r,co,k<<1|1); } else{ update(l,mid,co,k<<1); update(mid+1,r,co,k<<1|1); } pushup(k); }}int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ build(1,n,1); while(m--){ int cao; scanf("%d",&cao); if(cao==1){ int w; scanf("%d",&w); if(a[1].sum<w){ printf("0\n"); } else{ int ans=query(1,n,w,1); printf("%d\n",ans); update(ans,ans+w-1,1,1); //cout<<1<<endl; } } else{ int x,y; scanf("%d%d",&x,&y); update(x,x+y-1,0,1); } } } return 0;}
0 0
- POJ3667---线段树
- 【poj3667】【线段树】Hotel
- 【线段树】Hotel POJ3667
- POJ3667 Hotel(线段树)
- poj3667线段树
- poj3667 线段树
- 线段树 poj3667 Hotel
- 【POJ3667】Hotel-线段树
- poj3667 线段树
- 线段树poj3667
- poj3667 线段树区间更新
- poj3667线段树区间合并
- poj3667 线段树+区间合并
- poj3667(线段树区间合并)
- 线段树区间合并poj3667
- poj3667 线段树区间合并
- poj3667(线段树区间合并)
- POJ3667(线段树区间合并)
- To-read
- thrift安装时出现的问题
- 中介者模式(Mediator Pattern)
- cuda 1000 32 block 256 threads 2 改进
- Java两则常见错误详析及解决
- poj3667线段树
- 【Python基础教程】第4章 字典
- J2EE面试题集锦(附答案)
- jni.h头文件详解(一)
- 黑马程序员——线程的总结(二)
- insmod: error inserting './scull.ko': -1 Unknown symbol in module
- OpenCV 决策树 之 理论准备
- SQL
- Unity3D【Mono Develop脚本编辑器介绍】