http://acm.sdut.edu.cn:8080/vjudge/contest/view.action?cid=216#problem/G
有n个花盆编号0-n-1,初始都没有种花,有两种操作:
1 a b 从a开始种花,但a处不一定能种,要种b朵花,若花盆中已种花就跳过不种,直到n-1,若b朵花种不完就扔掉,输出种b朵花的花盆左右端点。
2 a b要清理[a,b]的花盆,先输出[a,b]的花的数目,然后清空这些花。
第二种操作简单,重点是第一种操作,寻找左右端点都是二分查找,首先应该找出从a起第一个能种花的花盆l,然后根据左端点l二分处右端点r使得[l,r]的能种花的个数是b。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <list> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> //#define LL long long #define LL __int64 #define eps 1e-12 #define PI acos(-1.0) using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 500010; struct node { int l,r; int sum; int col; } tree[maxn*4]; void build(int v, int l, int r) { tree[v].l = l; tree[v].r = r; tree[v].sum = 0; tree[v].col = 0; if(l == r) return; int mid = (l+r) >> 1; build(v*2,l,mid); build(v*2+1,mid+1,r); } void push_down(int v) { if(tree[v].l == tree[v].r || tree[v].col == -1) return; tree[v*2].col = tree[v*2+1].col = tree[v].col; if(tree[v].col == 1) { tree[v*2].sum = tree[v*2].r - tree[v*2].l + 1; tree[v*2+1].sum = tree[v*2+1].r - tree[v*2+1].l + 1; } else tree[v*2].sum = tree[v*2+1].sum = 0; tree[v].col = -1; } int query(int v, int l, int r) { if(tree[v].l == l && tree[v].r == r) return tree[v].sum; push_down(v); int mid = (tree[v].l + tree[v].r)>>1; if(r <= mid) return query(v*2,l,r); else if(l > mid) return query(v*2+1,l,r); else return query(v*2,l,mid) + query(v*2+1,mid+1,r); } int Binsearch(int l, int r, int key) { int low = l,high = r,mid; int res; while(high >= low) { mid = (low + high) >> 1; res = query(1,l,mid); if(mid-l+1 - res < key) low = mid+1; else high = mid-1; } return low; } void update(int v, int l, int r, int col) { if(tree[v].l == l && tree[v].r == r) { tree[v].col = col; if(tree[v].col == 1) tree[v].sum = tree[v].r - tree[v].l + 1; else tree[v].sum = 0; return; } push_down(v); int mid = (tree[v].l + tree[v].r) >> 1; if(r <= mid) update(v*2,l,r,col); else if(l > mid) update(v*2+1,l,r,col); else { update(v*2,l,mid,col); update(v*2+1,mid+1,r,col); } tree[v].sum = tree[v*2].sum + tree[v*2+1].sum; } int main() { int test; int n,m,a,b,res,l,r,res1,op; scanf("%d",&test); while(~scanf("%d %d",&n,&m)) { build(1,0,n-1); while(m--) { scanf("%d %d %d",&op,&a,&b); if(op == 1) { res = query(1,a,n-1); if(n-a == res) printf("Can not put any one.\n"); else { if(a == 0) res1 = 0; //wa了一次,a=0时a-1越界。 else res1 = query(1,0,a-1); //询问[0,a-1]的已种的花 l = Binsearch(0,n-1,a-res1+1);//二分查找[0,n-1]中的l使得[0,l]的可以种的花为a-res1+1,这个l就是要找的左端点 b = min(n-a-res,b);//b取[a,n-1]可以种的花数与b的较小值 r = Binsearch(l,n-1,b);//二分查找r使得[l,r]中可以种的花为b printf("%d %d\n",l,r); update(1,l,r,1); } } else { res = query(1,a,b); printf("%d\n",res); update(1,a,b,0); } } printf("\n"); } return 0; }