Sample Input
2 10 5 1 3 5 2 4 5 1 1 8 2 3 6 1 8 8 10 6 1 2 5 2 3 4 1 0 8 2 2 5 1 4 4 1 2 3
Sample Output
3 7 2 1 9 4 Can not put any one. 2 6 2 0 9 4 4 5 2 3
Can not put any one. ,能插输出插花的起始和尾的位置 . 2操作, 在 a.b花瓶间把花瓶清空,输入清空的花的数量.
操作1:每次查询区间 [A, N - 1] 中第一个空格的位置,然后在[ A, N - 1 ]中二分右端点的位置。实际放的花的数量是 要求数量 与 剩余空格数量 之间的最小值。
如果[ A, N - 1 ]中已经没有空格了,就不能放了。
操作2:求和与成端更新,线段树基本操作不解释
#include <cstdio>
#include <cstring>#include <cstdlib>
#include <algorithm>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
using namespace std;
const int MAXN = 50010;
const int INF = 1 << 30;
int N, Q, ok;
int flag[ MAXN << 2 ]; //无标记:-1,清空:0,占用:1
int sum[ MAXN << 2 ]; //区间占用区域总和
int len[ MAXN << 2 ]; //空闲区域长度总和
int addr[ MAXN << 2 ]; //本区间第一个空格的位置
void PushUp( int rt, int l, int r )
{
int lc = rt << 1;
int rc = rt << 1 | 1;
sum[rt] = sum[lc] + sum[rc];
len[rt] = len[lc] + len[rc];
addr[rt] = min( addr[lc], addr[rc] );
return;
}
void PushDown( int rt, int l, int r )
{
int m = ( l + r ) >> 1;
int lc = rt << 1;
int rc = rt << 1 | 1;
if ( flag[rt] != -1 )
{
flag[lc] = flag[rc] = flag[rt];
if ( flag[rt] == 1 ) //如果占用
{
sum[lc] = m - l + 1;
sum[rc] = r - m;
len[lc] = len[rc] = 0;
addr[lc] = addr[rc] = INF; //本区间没有空格
}
else
{
sum[lc] = sum[rc] = 0;
len[lc] = m - l + 1;
len[rc] = r - m;
addr[lc] = l;
addr[rc] = m + 1;
}
flag[rt] = -1;
}
return;
}
void build( int l, int r, int rt )
{
flag[rt] = -1;
if ( l == r )
{
sum[rt] = 0;
len[rt] = r - l + 1;
addr[rt] = l;
return;
}
int m = ( l + r ) >> 1;
build( lson );
build( rson );
PushUp( rt, l, r );
return;
}
int QuerySum( int L, int R, int l, int r, int rt )
{
//printf( "preS: [%d, %d]: sum = %d\n", l, r, sum[rt] );
if ( L <= l && r <= R ) return sum[rt];
PushDown( rt, l, r );
int m = ( l + r ) >> 1;
int res = 0;
if ( L <= m ) res += QuerySum( L, R, lson );
if ( R > m ) res += QuerySum( L, R, rson );
PushUp( rt, l, r );
//printf( "afterS: [%d, %d]: sum = %d\n", l, r, sum[rt] );
return res;
}
//查询大于等于st的第一个空格的位置
int QueryConti( int L, int R, int l, int r, int rt )
{
if ( L <= l && r <= R )
{
return addr[rt];
}
PushDown( rt, l, r );
int m = ( l + r ) >> 1;
int tmp = INF;
if ( L <= m ) tmp = min( tmp, QueryConti( L, R, lson ) );
if ( R > m ) tmp = min( tmp, QueryConti( L, R, rson ) );
PushUp( rt, l, r );
return tmp;
}
void Update( int L, int R, int c, int l, int r, int rt )
{
//printf( "pre UP [%d, %d]: sum = %d\n", l, r, sum[rt] );
if ( L <= l && r <= R )
{
flag[rt] = c;
if ( flag[rt] == 1 ) //如果占用
{
sum[rt] = r - l + 1;
len[rt] = 0;
addr[rt] = INF; //本区间没有空格
}
else
{
sum[rt] = 0;
len[rt] = r - l + 1;
addr[rt] = l;
}
return;
}
PushDown( rt, l, r );
int m = ( l + r ) >> 1;
if ( L <= m ) Update( L, R, c, lson );
if ( R > m ) Update( L, R, c, rson );
PushUp( rt, l, r );
//printf( "after UP [%d, %d]: sum = %d\n", l, r, sum[rt] );
return;
}
int BiSearch( int l, int r, int st, int tar )
{
//printf("tar=%d\n", tar);
while ( l <= r )
{
int mid = ( l + r ) >> 1;
int sum = QuerySum( st, mid, 0, N - 1, 1 );
sum = mid - st + 1 - sum;
if ( sum >= tar ) r = mid;
else l = mid + 1;
if ( l == r ) return l;
}
return l;
}
int main()
{
//freopen( "s.out", "w", stdout );
int T;
scanf( "%d", &T );
while( T-- )
{
scanf( "%d%d", &N, &Q );
build( 0, N - 1, 1 );
while ( Q-- )
{
int op, a, b;
scanf( "%d%d%d", &op, &a, &b );
if ( op == 1 )
{
if ( b == 0 ) continue;
int ans = QuerySum( a, N - 1, 0, N - 1, 1 );
if ( ans == N - a )
puts("Can not put any one.");
else
{
//printf( "%d %d\n", N - a, ans );
int FF = min( N - a - ans, b );
int left = QueryConti( a, N - 1, 0, N - 1, 1 );
int right = BiSearch( a, N - 1, a, FF );
printf( "%d %d\n", left, right );
Update( left, right, 1, 0, N - 1, 1 );
}
}
else
{
int ans = QuerySum( a, b, 0, N - 1, 1 );
printf( "%d\n", ans );
Update( a, b, 0, 0, N - 1, 1 );
}
//puts("**********");
}
puts("");
}
return 0;
}