poj3667
题意
给出n,m(1<=N,M<=50000),表示一个有N个空位的数列,对其进行M次操作
给出两种操作:
1 Di:表示将数列中最左端的连续Di个空位填满,输出被填满区间左端点的位置,若无法做到则不填并输出0
2 Xi Di:将区间[Xi,Xi+Di-1]清空
题目分析
建一棵线段树,每个节点维护该区间内最大左/右连续空位和最大连续空位和标记f,f==1表示该区间被填满,f==-1表示该区间被清空。利用标记f对线段树进行区间操作。
代码(AC)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=55000;
int n,m;
struct Node{
int l,r;
int ln,rn,n;
int flag;
Node *lt,*rt;
Node(int l1,int r1){
l=l1; r=r1;
ln=rn=n=flag=0;
lt=rt=NULL;
}
};
Node *root;
inline void pushdown(Node *p){
if (p->flag==1) p->ln=p->rn=p->n=0;
if (p->flag==-1) p->ln=p->rn=p->n=p->r-p->l+1;
if (p->lt && p->flag!=0) p->lt->flag=p->rt->flag=p->flag;
p->flag=0;
}
inline void update(Node *p){
if (!p->lt){
if (p->flag==1) p->ln=p->rn=p->n=0;
if (p->flag==-1 || p->flag==0) p->ln=p->rn=p->n=1;
return;
}
pushdown(p->lt); pushdown(p->rt);
if (p->lt->n==p->lt->r-p->lt->l+1) p->ln=p->lt->n+p->rt->ln;
else p->ln=p->lt->ln;
if (p->rt->n==p->rt->r-p->rt->l+1) p->rn=p->rt->n+p->lt->rn;
else p->rn=p->rt->rn;
p->n=max(p->lt->rn+p->rt->ln,max(p->lt->n,p->rt->n));
}
void build(Node *&p,int l,int r){
p=new Node(l,r);
if (l<r){
int mid=(l+r)>>1;
build(p->lt,l,mid);
build(p->rt,mid+1,r);
}
update(p);
}
void print(Node *p){
if (p->lt) print(p->lt);
printf("%d (%d,%d) %d %d %d %d %d %d\n",p,p->l,p->r,p->ln,p->rn,p->n,p->flag,p->lt,p->rt);
if (p->rt) print(p->rt);
}
int find(Node *p,int dis){
pushdown(p);
if (p->n<dis) return 0;
if (p->ln>=dis) return p->l;
if (p->lt && p->lt->n>=dis) return find(p->lt,dis);
if (p->lt->rn+p->rt->ln>=dis) return p->lt->r-p->lt->rn+1;
if (p->rt && p->rt->n>=dis) return find(p->rt,dis);
return 0;
}
void ins(Node *p,int u,int v){
pushdown(p);
if (u<=p->l && p->r<=v){
p->flag=1;
p->ln=p->rn=p->n=0;
return;
}
int mid=(p->l+p->r)>>1;
if (u<=mid) ins(p->lt,u,v);
if (mid+1<=v) ins(p->rt,u,v);
update(p);
}
void del(Node *p,int u,int v){
pushdown(p);
if (u<=p->l && p->r<=v){
p->flag=-1;
p->ln=p->rn=p->n=p->r-p->l+1;
return;
}
int mid=(p->l+p->r)>>1;
if (u<=mid) del(p->lt,u,v);
if (mid+1<=v) del(p->rt,u,v);
update(p);
}
int main(){
//freopen("hotel.12.in","r",stdin);
//freopen("hotel.out","w",stdout);
scanf("%d%d",&n,&m);
build(root,1,n);
//print(root);
int type,d,x;
for (int i=1; i<=m; i++){
scanf("%d",&type);
if (type==1){
scanf("%d",&d);
int answer=find(root,d);
printf("%d\n",answer);
if (answer) ins(root,answer,answer+d-1);
}
if (type==2){
scanf("%d%d",&x,&d);
del(root,x,x+d-1);
}
//print(root);
}
return 0;
}