题目链接:HDU-4614-Vases and Flowers
题意是有n个花瓶在一个线段上,用0~n-1来标记,有两种操作,第一种是从x开始插花,一直向后插y个花,如果一个花瓶里已经插有花,则不能再插,求第一个插花的位置和最后一个插花的位置,如果一朵花都插不了的话,输出"Can not put any one"。第二种操作是将x到y花瓶里的花拿出来,并输出拿出来的花数。
很容易想到用线段树来做,设sum[i]为区间i内花的数量。插花操作首先要找到插花的具体区间,如果[x,n-1]中插满了花,显然是不能插花的,否则我们用二分来找右端点r使得[x,r]内空花瓶的数量为y或者r等于n-1(r==n-1当且仅当区间[x,n-1]内的空花瓶数量小于y) 。 然后通过两个函数find_l和find_r来找左端点和右端点(其实也可以通过二分来找的,定义两层偏序。。),找到左右端点后,更新sum。清空花瓶操作直接更新sum就行了。
#include
#include
#include
using namespace std;
const int maxn=5e4+7;
int sum[maxn<<2],n;
void push_down(int now,int l,int r)
{
if(sum[now]==r-l+1)
{
int mid=(l+r)>>1;
sum[now<<1]=mid-l+1;
sum[now<<1|1]=r-mid;
}
else if(sum[now]==0)
sum[now<<1]=sum[now<<1|1]=0;
}
void push_up(int now)
{
sum[now]=sum[now<<1]+sum[now<<1|1];
}
void update(int now,int l,int r,int ul,int ur,int s)
{
if(ul<=l&&ur>=r)
{
sum[now]=s*(r-l+1);
return ;
}
if(l==r) return ;
push_down(now,l,r);
int mid=(l+r)>>1;
if(ul<=mid) update(now<<1,l,mid,ul,ur,s);
if(ur>mid) update(now<<1|1,mid+1,r,ul,ur,s);
push_up(now);
}
int query(int now,int l,int r,int ql,int qr)
{
if(ql<=l&&qr>=r) return sum[now];
int mid=(l+r)>>1,res=0;
push_down(now,l,r);
if(ql<=mid) res+=query(now<<1,l,mid,ql,qr);
if(qr>mid) res+=query(now<<1|1,mid+1,r,ql,qr);
return res;
}
int find_l(int now,int l,int r,int ql,int qr)
{
if(l==r) return l;
int mid=(l+r)>>1;
if(ql<=mid&&query(1,0,n-1,ql,mid)!=mid-ql+1) return find_l(now<<1,l,mid,ql,qr);
else return find_l(now<<1|1,mid+1,r,ql,qr);
}
int find_r(int now,int l,int r,int ql,int qr)
{
if(l==r) return l;
int mid=(l+r)>>1;
if(qr>mid&&query(1,0,n-1,mid+1,qr)!=qr-mid) return find_r(now<<1|1,mid+1,r,ql,qr);
else return find_r(now<<1,l,mid,ql,qr);
}
int main()
{
int T,m;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
int o,x,y;
memset(sum,0,sizeof(sum));
for(int i=0;il)
{
mid=(l+r)>>1;
if(mid-x+1-query(1,0,n-1,x,mid)>=y)
r=mid;
else l=mid+1;
}
int ll=find_l(1,0,n-1,x,r);
int rr=find_r(1,0,n-1,x,r);
printf("%d %d\n",ll,rr);
update(1,0,n-1,ll,rr,1);
}
}
else
{
printf("%d\n",query(1,0,n-1,x,y));
update(1,0,n-1,x,y,0);
}
}
puts("");
}
return 0;
}