http://poj.org/problem?id=3667
题意:有一个线段,从1到n,下面m个操作,操作分两个类型,以1开头的是查询操作,以2开头的是更新操作
1 查询操作,找一段长度为W的没被覆盖的最左的区间
2 更新操作,将(x,x+D)连续的区域清空
引用巨巨的题解:
http://www.cnblogs.com/scau20110726/archive/2013/05/07/3065418.html
精华就是用了 tlen,llen,rlen,
比较精巧的地方就是 tr[i].llen和tr[i].rlen怎么从tr[i<<1],tr[i<<1|1]推来。
还有查找的时候三个方面:
- 左子树
- 左子树一部分+右子树一部分
- 右子树
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
#define lson l,mid,i<<1
#define rson mid+1,r,i<<1|1
const int N = 50000+10;
struct Node
{
int tot,ll,rr;
int flag;
}tr[N*4];
void built(int l,int r,int i)
{
tr[i].tot=tr[i].ll=tr[i].rr=r-l+1;
tr[i].flag=0;
if(l==r) return;
int mid=(l+r)>>1;
built(lson);
built(rson);
tr[i].tot = max(max(tr[i<<1].tot,tr[i<<1|1].tot),tr[i<<1].rr+tr[i<<1|1].ll);
return;
}
void pushdown(int l,int r,int i)
{
tr[i<<1].flag=tr[i<<1|1].flag=tr[i].flag;
tr[i].flag=-1;
int mid=(l+r)>>1;
if(tr[i<<1].flag) tr[i<<1].tot=tr[i<<1].ll=tr[i<<1].rr=0;
else tr[i<<1].tot=tr[i<<1].ll=tr[i<<1].rr=mid-l+1;
if(tr[i<<1|1].flag) tr[i<<1|1].tot=tr[i<<1|1].ll=tr[i<<1|1].rr=0;
else tr[i<<1|1].tot=tr[i<<1|1].ll=tr[i<<1|1].rr=r-mid;
return;
}
int query(int l,int r,int i,int x)
{
if(l==r && x==1) return l;
if(tr[i].flag!=-1) pushdown(l,r,i);
int mid=(l+r)>>1;
if(tr[i<<1].tot>=x) return query(lson,x);
else if(tr[i<<1].rr+tr[i<<1|1].ll>=x) return mid-tr[i<<1].rr+1;
else if(tr[i<<1|1].tot>=x) return query(rson,x);
else return 0;
}
void update(int l,int r,int i,int a,int b,int sta)
{
if(l>=a && r<=b)
{
tr[i].flag=sta;
if(sta) tr[i].tot=tr[i].ll=tr[i].rr=0;
else tr[i].tot=tr[i].ll=tr[i].rr=r-l+1;
return;
}
if(tr[i].flag!=-1) pushdown(l,r,i);
int mid=(l+r)>>1;
if(mid>=a) update(lson,a,b,sta);
if(mid<b) update(rson,a,b,sta);
tr[i].tot=max(max(tr[i<<1].tot,tr[i<<1|1].tot),tr[i<<1].rr+tr[i<<1|1].ll);
tr[i].ll= tr[i<<1].ll;
tr[i].rr= tr[i<<1|1].rr;
if(tr[i<<1].tot == mid-l+1) tr[i].ll+=tr[i<<1|1].ll;
if(tr[i<<1|1].tot==r-mid) tr[i].rr+=tr[i<<1].rr;
return;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
built(1,n,1);
while(m--)
{
int op,x,y;
scanf("%d",&op);
if(op==1)
{
scanf("%d",&x);
int ans=query(1,n,1,x);
printf("%d\n",ans);
if(ans) update(1,n,1,ans,ans+x-1,1);
}
else
{
scanf("%d%d",&x,&y);
update(1,n,1,x,x+y-1,0);
}
}
}
return 0;
}