G - Vases and Flowers(线段树+二分)

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




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值