这个题目其实不用二分应该能快点,感觉应该会写很多函数,很多种情况。
所以选择二分+线段树来实现起来简单点。
思路还算是比较简单的。
#include <iostream>
#include <cstdio>
#include <set>
using namespace std;
const int maxn = 100010;
int num[maxn<<2],mask[maxn<<2],ansl,ansr;
void pushdown(int l,int r,int rt)
{
if (mask[rt] == 1)
{
mask[rt<<1] = 1;
mask[rt<<1|1] = 1;
int m = (l+r)>>1;
num[rt<<1] = m-l+1;
num[rt<<1|1] = r-m;
mask[rt] = -1;
//cout << "bug" << endl;
} else if (mask[rt] == 0) {
mask[rt<<1] = 0;
mask[rt<<1|1] = 0;
num[rt<<1] = 0;
num[rt<<1|1] = 0;
mask[rt] = -1;
}
}
void pushup(int rt)
{
num[rt] = num[rt<<1] + num[rt<<1|1];
}
int query(int L,int R,int type,int l,int r,int rt)
{
if (L > R) return 0;
if (L <= l && R >= r) {
if (type == -1) return num[rt];
if (type == 1) {
int result = r - l + 1 - num[rt];
num[rt] = r - l + 1;
mask[rt] = 1;
return result;
}
int result = num[rt];
num[rt] = 0;
mask[rt] = 0;
return result;
}
int m = (l + r)>>1;
pushdown(l,r,rt);
int ret = 0;
if (L <= m) ret += query(L,R,type,l,m,rt<<1);
if (R > m) ret += query(L,R,type,m+1,r,rt<<1|1);
pushup(rt);
return ret;
}
int binary_find(int cnt,int n)
{
int l = 0 ,r = n - 1,ret = 0;
while(l <= r)
{
int m = (l+r)>>1;
int number = query(0,m,-1,0,n-1,1);
if (number >= cnt) {
ret = m;
r = m - 1;
} else l = m + 1;
}
return ret;
}
void solve(int start,int cnt,int n)
{
int pre = query(0,start-1,-1,0,n-1,1);
int behind = query(start,n-1,-1,0,n-1,1);
//cout << pre << " " << behind << endl;
cnt = min(cnt,behind);
if (cnt == 0) return;
ansl = binary_find(pre+1,n);
ansr = binary_find(pre + cnt,n);
query(ansl,ansr,0,0,n-1,1);
}
int main()
{
int T,n,m,K,A,B;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
//线段树初始化
num[1] = n;
mask[1] = 1;
while(m--)
{
scanf("%d %d %d",&K,&A,&B);
if (K == 1) {
ansl = ansr = -1;
solve(A,B,n);
if (ansl != -1) printf("%d %d\n",ansl,ansr);
else puts("Can not put any one.");
} else {
printf("%d\n",query(A,B,1,0,n-1,1));
}
}
puts("");
}
return 0;
}