Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A and try to put a flower in the vase. If the there is no flower in the vase, she will put a flower in it, otherwise she skip this vase. And then she will try put in the vase A+1, A+2, …, N-1, until there is no flower left or she has tried the vase N-1. The left flowers will be discarded. Of course, sometimes she will clean the vases. Because there are too many vases, she randomly choose to clean the vases numbered from A to B(A <= B). The flowers in the cleaned vases will be discarded.
有编号从0到n-1的花瓶,一共有两种操作,操作1是将f朵花从a瓶开始到n-1瓶往后放,如果能的话就输出开始的位置(放置有规则,要从a瓶开始尝试,如果这一瓶不可以的话,就跳过,一直往后试),如果都不行的话,那么就输出Can not put any one.,操作2是将从x到y的花瓶清空掉,输出清空的瓶子的数量。
二分加线段树。首先二分搜索左侧位置,也就是查询的时候空花瓶个数大于等于1的位置,也就是第一个空花瓶的位置,确定了左端点,二分查找右端点。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4+5;
struct node
{
int val, lazy, len;
}tree[maxn<<2];
int T, n, m;
void build(int l, int r, int cur)
{
tree[cur].lazy = -1;
tree[cur].val = 1;
tree[cur].len = r-l+1;
if(l == r) return ;
int mid = (l+r)>>1;
build(l, mid, cur<<1);
build(mid+1, r, cur<<1|1);
tree[cur].val = tree[cur<<1].val+tree[cur<<1|1].val;
}
void pushDown(int cur)
{
if(tree[cur].lazy == -1) return ;
tree[cur<<1].lazy = tree[cur<<1|1].lazy = tree[cur].lazy;
tree[cur<<1].val = tree[cur<<1].len*tree[cur].lazy;
tree[cur<<1|1].val = tree[cur<<1|1].len*tree[cur].lazy;
tree[cur].lazy = -1;
}
int query(int L, int R, int l, int r, int cur)
{
if(L <= l && r <= R) return tree[cur].val;
pushDown(cur);
int mid = (l+r)>>1;
int sum = 0;
if(L <= mid) sum += query(L, R, l, mid, cur<<1);
if(R > mid) sum += query(L, R, mid+1, r, cur<<1|1);
return sum;
}
void update(int L, int R, int l, int r, int cur, int val)
{
if(L <= l && r <= R)
{
tree[cur].lazy = val;
tree[cur].val = tree[cur].len*val;
return ;
}
pushDown(cur);
int mid = (l+r)>>1;
if(L <= mid) update(L, R, l, mid, cur<<1, val);
if(mid < R) update(L, R, mid+1, r, cur<<1|1, val);
tree[cur].val = tree[cur<<1].val+tree[cur<<1|1].val;
}
int Find_Left(int l, int r)
{
int ans = -1;
int low = l, high = r;
while(low <= high)
{
int mid = (low+high)>>1;
int temp = query(l, mid, 1, n, 1);
if(temp >= 1)
{
ans = mid;
high = mid-1;
}
else low = mid+1;
}
return ans;
}
int Find_Right(int l, int q)
{
int low = l, high = n;
int ans = -1;
int _min = min(q, query(l, n, 1, n, 1));
while(low <= high)
{
int mid = (low+high)>>1;
int temp = query(l, mid, 1, n, 1);
if(temp >= _min) high = mid-1;
else low = mid+1;
if(temp == _min) ans = mid;
}
return ans;
}
int main()
{
cin >> T;
while(T--)
{
scanf("%d%d", &n, &m);
build(1, n, 1);
int q, x, y;
while(m--)
{
scanf("%d%d%d", &q, &x, &y);
if(q == 2)
{
x++; y++;
printf("%d\n", y-x+1-query(x, y, 1, n, 1));
update(x, y, 1, n, 1, 1);
}
if(q == 1)
{
x++;
if(query(x, n, 1, n, 1) == 0 || y == 0)
{
printf("Can not put any one.\n");
continue ;
}
int L = Find_Left(x, n);
int R = Find_Right(L, y);
printf("%d %d\n", L-1, R-1);
update(L, R, 1, n, 1, 0);
}
}
printf("\n");
}
return 0;
}