这个题目其实不用二分应该能快点,感觉应该会写很多函数,很多种情况。
所以选择二分+线段树来实现起来简单点。
思路还算是比较简单的。
#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; }