题目
两种操作:
1 x y: 从x开始放,输出能放的起始位置,输出放的最后位置,不一定y朵花都有位置放!如果一朵也不能放,就输出....
2 x y: 清空操作,[x,y];
用1表示此花瓶是空的,那我们就是要查找某区间的和,清空操作就是区间全部变为1!
至于放花操作,我们首先需要找出x开始的第一个空花瓶,这个可以利用二分,
而找最后一个花瓶也要二分,查找一个点,使起点到这个点的区间和,尽可能的接近我们需要的值。
#include
#include
#include
using namespace std;
#define N 50010
struct node
{
int r,l;
int lazy,num;
}root[N*4];
inline void Pushup(int t)
{
root[t].num=root[t*2].num+root[t*2+1].num;
}
inline void pushdown(int t)
{
if(root[t].lazy!=-1)
{
root[t*2].lazy=root[t*2+1].lazy=root[t].lazy;
root[t*2].num=root[t*2].lazy*(root[t*2].r-root[t*2].l+1);
root[t*2+1].num=root[t*2+1].lazy*(root[t*2+1].r-root[t*2+1].l+1);
root[t].lazy=-1;
}
}
inline void build(int t,int x,int y)
{
root[t].l=x;
root[t].r=y;
root[t].num=(y-x+1);
root[t].lazy=-1;
if(x==y) return;
int m=(x+y)>>1;
build(t*2,x,m);
build(t*2+1,m+1,y);
}
inline void Modefiy(int t,int x,int y,int val)
{
int l=root[t].l;
int r=root[t].r;
if(l==x&&r==y)
{
root[t].lazy=val;
root[t].num=val*(r-l+1);
return;
}
pushdown(t);
int m=(l+r)>>1;
if(x<=m) Modefiy(t*2,x,min(y,m),val);
if(y>m) Modefiy(t*2+1,max(x,m+1),y,val);
Pushup(t);
}
inline int query(int t,int x,int y)
{
int l=root[t].l;
int r=root[t].r;
if(l==x&&r==y)
{
return root[t].num;
}
pushdown(t);
int m=(l+r)>>1;
int ans=0;
if(x<=m) ans+=query(t*2,x,min(m,y));
if(y>m) ans+=query(t*2+1,max(x,m+1),y);
return ans;
}
int main()
{
int ta;
scanf("%d",&ta);
for(int ca=1;ca<=ta;ca++)
{
int n,m;
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==2)
{
x++,y++;
printf("%d\n",y-x+1-query(1,x,y));
Modefiy(1,x,y,1);
}
else
{
x++;
if(query(1,x,n)==0)
{
puts("Can not put any one.");
}
else
{
int s=x,t=n;
int mi=n+1,m;
while(s<=t)
{
m=(s+t)>>1;
if(query(1,s,m)>=1)
{
mi=min(mi,m);
t=m-1;
}
else s=m+1;
}
s=mi;
t=n;
int temp=query(1,s,n);
if(temp>1;
int p=query(1,mi,m);
if(p==y)
{
mx=min(mx,m);
t=m-1;
}
else if(p>y) t=m-1;
else s=m+1;
}
printf("%d %d\n",mi-1,mx-1);
Modefiy(1,mi,mx,0);
}
}
}
printf("\n");
}
}