题意:给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花。
然后有2个操作。
操作1,a b c ,往在a位置后面(包括a)插b朵花,输出插入的首位置和末位置。
操作2,a b ,输出区间[a , b ]范围内的花的数量,然后全部清空。
很显然这是一道线段树。区间更新,区间求和,这些基本的操作线段树都可以logN的时间范围内完成。
操作2,很显然就是线段树的区间求和,求出[a , b]范围内的花朵的数量,区间更新,将整个区间全部变成0。
操作1,这里我们首先需要找出他的首位置和末位置,所以需要二分他的位置。
首先我们二分他的首位置, l = a , r = n ,在这个区间内二分,找出第一个0的位置,那就是该操作的首位置pos1。
然后再二分他的末位置,l = pos1 , r = n ,找到第b个0,就是该操作的末位置pos2,然后区间更新[pos1 ,pos2]全部置为1。
这两个二分写得时候要相当注意,很容易出错!
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 50100
#define lson (pos<<1)
#define rson (pos<<1|1)
struct node
{
int l,r,tag,sum;
} tree[N*4];
void build(int pos, int l, int r)
{
tree[pos].l=l;
tree[pos].r=r;
tree[pos].tag=0;
tree[pos].sum=r-l+1;
if(l==r)return ;
int mid=(l+r)/2;
build(lson,l,mid);
build(rson,mid+1,r);
}
void pushdown(int pos)
{
if(tree[pos].tag)
{
if(tree[pos].tag==2)
{
tree[lson].sum=(tree[lson].r-tree[lson].l+1);
tree[lson].tag=2;
tree[rson].sum=(tree[rson].r-tree[rson].l+1);
tree[rson].tag=2;
tree[pos].tag=0;
}
else
{
tree[lson].sum=0;
tree[lson].tag=1;
tree[rson].sum=0;
tree[rson].tag=1;
tree[pos].tag=0;
}
}
}
void pushup(int pos)
{
tree[pos].sum=tree[lson].sum+tree[rson].sum;
}
void update(int pos, int L, int R, int v)
{
if(L<=tree[pos].l&&tree[pos].r<=R)
{
if(v==1)
{
tree[pos].tag=1;
tree[pos].sum=0;
}
else if(v==2)
{
tree[pos].tag=2;
tree[pos].sum=tree[pos].r-tree[pos].l+1;
}
return ;
}
pushdown(pos);
int mid=(tree[pos].l+tree[pos].r)/2;
if(L<=mid)update(lson,L,R,v);
if(mid<R)update(rson,L,R,v);
pushup(pos);
}
int query(int pos, int L, int R)
{
if(L<=tree[pos].l&&tree[pos].r<=R)
{
return tree[pos].sum;
}
pushdown(pos);
int mid=(tree[pos].l+tree[pos].r)/2;
int ans=0;
if(L<=mid)ans+=query(lson,L,R);
if(mid<R)ans+=query(rson,L,R);
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i = 0; i < m; i++)
{
int id;
scanf("%d",&id);
if(id==1)
{
int A,B;
int s, w;
scanf("%d%d",&s,&w);
s++;
int sum=query(1,s,n);
sum=min(w,sum);
if(sum==0)
{
printf("Can not put any one.\n");
continue;
}
int l=s,r=n;
if(sum==1)
{
if(query(1,l,l))
{
A=l;
B=l;
printf("%d %d\n",A-1,B-1);
update(1,A,B,1);
continue;
}
}
sum--;
//printf("sum=%d\n",sum);
while(l+1<r)
{
int mid=(l+r)/2;
int tmp=query(1,s,mid);
//printf("mid=%d tmp=%d l=%d r=%d\n",mid,tmp,l,r);
if(tmp>sum)r=mid;
else l=mid;
}
B=r;
l=s;
r=B;
if(sum==0)
{
if(query(1,r,r))
{
A=r;
B=r;
printf("%d %d\n",A-1,B-1);
update(1,A,B,1);
continue;
}
}
while(l+1<r)
{
int mid=(l+r)/2;
int tmp=query(1,mid,B);
if(tmp>sum)l=mid;
else r=mid;
}
A=l;
printf("%d %d\n",A-1,B-1);
update(1,A,B,1);
}
else if(id==2)
{
int a,b;
scanf("%d%d",&a,&b);
a++;
b++;
int hehe=b-a+1-query(1,a,b);
printf("%d\n",hehe);
if(hehe!=0)
update(1,a,b,2);
}
}
printf("\n");
}
return 0;
}
/*2
10 5
1 0 1
1 0 2
1 0 1
*/