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;
}