/*
translation:
程序媛经常收到花:),现在有若干花瓶,以及对应的若干个操作,1 a b表示程序媛将从a号花瓶起,从左往右在每个空的
花瓶里放置1朵花,遇到花瓶里有花的就跳过。2 a b表示程序媛将清空a~b号
花瓶。对每个操作输出对应的信息,1操作输出最开始放置花和最后放置花的花瓶编号。2操作输出a~b之间的花朵数目。
solution:
线段树+二分
很容易想到对1操作二分找寻两个位置。其它还是常规写法。思路简单,编码麻烦。WA了若干次才写对!
note:
# 放到最后一个花瓶后如果手里还有花就丢掉,题意理解错误了ORZ。
# 二分好容易写错啊。
# 这段码效率较低,g++能过,c++就TLE
# 线段树码真心长,明天绝逼不训线段树了。括弧笑:)
date:
2016.12.1
*/
#include
#include
using namespace std;
const int maxn = 50000 + 5;
int s[maxn*4], e[maxn*4];
int sum[maxn*4], lazy[maxn*4];
int n, m, res_flower;
void build(int l, int r, int o)
{
s[o] = l;
e[o] = r;
sum[o] = 0;
lazy[o] = -1;
if(l != r){
int m = (l + r) >> 1;
build(l, m, o << 1);
build(m+1, r, o << 1 | 1);
}
}
void push_down(int o, int num)
{
int lc = o << 1, rc = o << 1 | 1;
if(lazy[o] != -1){
lazy[lc] = lazy[rc] = lazy[o];
sum[lc] = lazy[lc] * (num - (num >> 1));
sum[rc] = lazy[rc] * (num >> 1);
lazy[o] = -1;
}
}
inline void push_up(int o)
{
sum[o] = sum[o << 1] + sum[o << 1 | 1];
}
void update(int x, int l, int r, int o) //将l~r的元素改成x
{
if(s[o] == l && e[o] == r){
lazy[o] = x;
sum[o] = x * (r - l + 1);
return;
}
if(s[o] == e[o]) return;
push_down(o, e[o]-s[o]+1);
int m = (s[o] + e[o]) >> 1;
if(r <= m) update(x, l, r, o << 1);
else if(l > m) update(x, l, r, o << 1 | 1);
else{
update(x, l, m, o << 1);
update(x, m+1, r, o << 1 | 1);
}
push_up(o);
}
int query(int l, int r, int o)
{
if(s[o] == l && e[o] == r){
return sum[o];
}
push_down(o, e[o]-s[o]+1);
int res = 0;
int m = (s[o] + e[o]) >> 1;
if(r <= m) res += query(l, r, o << 1);
else if(l > m) res += query(l, r, o << 1 | 1);
else{
res += query(l, m, o << 1);
res += query(m+1, r, o << 1 | 1);
}
return res;
}
int find_pre(int a, int f)
{
int lb = a, ub = n, mid;
for(int i = 0; i < 50; i++){
mid = (lb + ub) >> 1;
int len = n - mid + 1;
if(len - query(mid, n, 1) >= f) lb = mid;
else ub = mid;
}
return mid;
}
int find_suf(int st, int f) //验证从st位置到mid位置是否有f个空花瓶
{
int lb = st, ub = n, mid;
for(int i = 0; i < 50; i++){
mid = (lb + ub) >> 1;
int len = mid - st + 1;
if(len - query(st, mid, 1) >= f) ub = mid;
else lb = mid;
}
return ub;
}
int find_suf2(int st, int f)
{
int lb = st, ub = n, mid;
for(int i = 0; i < 50; i++){
mid = (lb + ub) >> 1;
int len = mid - st + 1;
if(len - query(st, mid, 1) < f) lb = mid;
else ub = mid;
}
return ub;
}
int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
build(1, n, 1);
res_flower = 0;
int op, a, b;
while(m--){
scanf("%d", &op);
if(op == 1){
scanf("%d%d", &a, &b);
a++;
int len = n - a + 1;
if(len-query(a, n, 1) == 0) printf("Can not put any one.\n");
else{
int pre = find_pre(a, len - query(a, n, 1)), suf;
if(n - pre + 1 - query(pre, n, 1) < b) suf = find_suf2(a, len - query(a, n, 1));
else suf = find_suf(a, b);
printf("%d %d\n", pre-1, suf-1);
update(1, pre, suf, 1);
}
}else{
scanf("%d%d", &a, &b);
a++; b++;
printf("%d\n", query(a, b, 1));
update(0, a, b, 1);
}
}
printf("\n");
}
return 0;
}