Vases and Flowers (HDU - 4614,线段树 + 二分 + 思维)

一.题目链接:

HDU-4614

二.题目大意:

有 N 个花盆,起初都没有花.

1 个花盆只能插 1 朵花.

有 m 次 2 种操作.

① 1 A F:从第 A 花盆开始插 F 朵花,多余的丢弃.

若一朵花都无法插入,则输出 "Can not put any one."

否则,输出插花的起点、终点.

② 2 A B:将 A ~ B 花盆中的花丢弃,并输出所丢弃的花的个数.

三.分析:

这个题难就难在 ①. 太菜了...

先查一遍 A ~ N 中的还可以插花的个数.

如果个数为 0,则输出 "Can not put any one."

否则,需确定最小的 L 和 R(二分查找).

四.代码实现:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;

const int M = (int)5e4;

struct node
{
    int l;
    int r;
    int w;
    int f;
} tree[M * 4 + 5];

void build(int k, int l, int r)
{
    tree[k].l = l;
    tree[k].r = r;
    tree[k].w = 0;
    tree[k].f = -1;
    if(l == r)
        return;
    int mid = (l + r) / 2;
    build(k * 2, l, mid);
    build(k * 2 + 1, mid + 1, r);
}

void push(int k)
{
    tree[k * 2].f = tree[k * 2 + 1].f = tree[k].f;
    tree[k * 2].w = tree[k].f * (tree[k * 2].r - tree[k * 2].l + 1);
    tree[k * 2 + 1].w = tree[k].f * (tree[k * 2 + 1].r - tree[k * 2 + 1].l + 1);
    tree[k].f = -1;
}

int query(int k, int l, int r, int a, int b)
{
    if(r < a || l > b)
        return 0;
    if(l >= a && r <= b)
        return tree[k].w;
    if(~tree[k].f)
        push(k);
    int cnt = 0;
    int mid = (l + r) / 2;
    if(a <= mid)
        cnt += query(k * 2, l, mid, a, b);
    if(mid < b)
        cnt += query(k * 2 + 1, mid + 1, r, a, b);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
    return cnt;
}

void interver(int k, int l, int r, int a, int b, int c)
{
    if(l >= a && r <= b)
    {
        tree[k].w = c * (tree[k].r - tree[k].l + 1);
        tree[k].f = c;
        return;
    }
    if(~tree[k].f)
        push(k);
    int mid = (l + r) / 2;
    if(a <= mid)
        interver(k * 2, l, mid, a, b, c);
    if(mid < b)
        interver(k * 2 + 1, mid + 1, r, a, b, c);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}

int binary(int x, int n, int num)
{
    int l = x;
    int r = n;
    while(l < r)
    {
        int mid = (l + r) / 2;
        if(mid - x + 1 - query(1, 1, n, x, mid) >= num)
            r = mid;
        else
            l = mid + 1;
    }
    return r;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n, m;
        scanf("%d %d", &n, &m);
        build(1, 1, n);
        while((m--) > 0)
        {
            int dir, a, b;
            scanf("%d %d %d", &dir, &a, &b);
            if(dir == 1)
            {
                a++;
                int cnt = n - a + 1 - query(1, 1, n, a, n);
                if(!cnt)
                {
                    printf("Can not put any one.\n");
                    continue;
                }
                int l = binary(a, n, 1);
                int r = binary(a, n, min(b, cnt));
                printf("%d %d\n", l - 1, r - 1);
                interver(1, 1, n, l, r, 1);
            }
            else if(dir == 2)
            {
                a++;
                b++;
                int cnt = query(1, 1, n, a, b);
                printf("%d\n", cnt);
                interver(1, 1, n, a, b, 0);
            }
        }
        printf("\n");
    }
    return 0;
}

 

你可能感兴趣的:(#,线段树,#,思维,#,二分)