#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
const int maxn=50005;
struct node{
int l;//区间的左端点
int r;//区间的右端点
int sum;//该区间的最长空闲区间的长度
int lsum;//从该区间的左端点起,最长的空闲区间长度
int rsum;//从该区间的右端点起,最长的空闲区间的长度
int cov;//cov=-1时表示该区间不能向下pushdown,cov=1时表示该区间已经全部填满,cov=0时表示该区间全部为空闲区
}tree[maxn<<2];
void build(int m,int l,int r)
{
int mid=(l+r)>>1;
tree[m].l=l;
tree[m].r=r;
tree[m].sum=r-l+1;
tree[m].lsum=r-l+1;
tree[m].rsum=r-l+1;
tree[m].cov=-1;
if(l==r){
return ;
}
build(m<<1,l,mid);
build(m<<1|1,mid+1,r);
}
void pushdown(int m)
{
if(tree[m].cov==-1)return ;
tree[m<<1].cov=tree[m<<1|1].cov=tree[m].cov;
if(tree[m].cov==1){
tree[m<<1].sum=tree[m<<1].lsum=tree[m<<1].rsum=0;
tree[m<<1|1].sum=tree[m<<1|1].lsum=tree[m<<1|1].rsum=0;
}
else{
tree[m<<1].sum=tree[m<<1].lsum=tree[m<<1].rsum=tree[m<<1].r-tree[m<<1].l+1;
tree[m<<1|1].sum=tree[m<<1|1].lsum=tree[m<<1|1].rsum=tree[m<<1|1].r-tree[m<<1|1].l+1;
}
tree[m].cov=-1;
}
void pushup(int m,int l,int r)
{
tree[m].lsum=tree[m<<1].lsum;
tree[m].rsum=tree[m<<1|1].rsum;
int mid=(l+r)>>1;
if(tree[m].lsum==mid-l+1)tree[m].lsum+=tree[m<<1|1].lsum;
if(tree[m].rsum==r-mid)tree[m].rsum+=tree[m<<1].rsum;
tree[m].sum=max(max(tree[m<<1].sum,tree[m<<1|1].sum),tree[m<<1].rsum+tree[m<<1|1].lsum);
}
int query(int m,int l,int r,int p)
{
//printf("%d %d\n",l,r);
if(l==r){
return l;
}
pushdown(m);//如果当前还没查询到所要的区间,就要及时pushdown,因为这样会节约一些不必要的操作
//只有该区间的cov值为0或则为1时,才会向左右子区间下压,
int mid=(l+r)>>1;
if(tree[m<<1].sum>=p)return query(m<<1,l,mid,p);
else
if(tree[m<<1].rsum+tree[m<<1|1].lsum>=p)
return mid-tree[m<<1].rsum+1;
else
return query(m<<1|1,mid+1,r,p);
}
void update(int m,int l,int r,int p)
{
//printf("%d %d\n",tree[m].l,tree[m].r);
if(tree[m].l>=l&&tree[m].r<=r){
//printf("%d %d\n",tree[m].l,tree[m].r);
tree[m].cov=p;
if(p==1){
tree[m].sum=tree[m].lsum=tree[m].rsum=0;
}
else{
tree[m].sum=tree[m].lsum=tree[m].rsum=tree[m].r-tree[m].l+1;
}
return ;
}
pushdown(m);//更新时也不要忘记向下pushdown
int mid=(tree[m].l+tree[m].r)>>1;
if(l<=mid)
update(m<<1,l,r,p);
if(r>mid)
update(m<<1|1,l,r,p);
pushup(m,tree[m].l,tree[m].r);//向上更新父节点区间的lsum,sum,rsum,但不能对父节点的cov值进行操作
} //因为你不能保证左右子节点区间的cov的值相同且不为-1
int n,m;
int main()
{
while(scanf("%d%d",&n,&m)!=EOF){
build(1,1,n);
while(m--){
/*for(int i=1;i<=4*n;i++){
printf("%d %d %d\n",tree[i].sum,tree[i].lsum,tree[i].rsum);
}*/
int op;
scanf("%d",&op);
if(op==1){
int x;
scanf("%d",&x);
if(tree[1].sum<x){
printf("0\n");
continue;
}
else{
int tmp=query(1,1,n,x);
printf("%d\n",tmp);
//printf("%d %d\n",tmp,tmp+x-1);
update(1,tmp,x+tmp-1,1);
}
}
else{
int a,b;
scanf("%d%d",&a,&b);
update(1,a,a+b-1,0);
}
//printf("okkkk\n");
}
}
return 0;
}
POJ - 3667(线段树区间合并)
最新推荐文章于 2020-08-03 23:44:34 发布