Vases and Flowers(线段树+二分)

Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A and try to put a flower in the vase. If the there is no flower in the vase, she will put a flower in it, otherwise she skip this vase. And then she will try put in the vase A+1, A+2, …, N-1, until there is no flower left or she has tried the vase N-1. The left flowers will be discarded. Of course, sometimes she will clean the vases. Because there are too many vases, she randomly choose to clean the vases numbered from A to B(A <= B). The flowers in the cleaned vases will be discarded.

有编号从0到n-1的花瓶,一共有两种操作,操作1是将f朵花从a瓶开始到n-1瓶往后放,如果能的话就输出开始的位置(放置有规则,要从a瓶开始尝试,如果这一瓶不可以的话,就跳过,一直往后试),如果都不行的话,那么就输出Can not put any one.,操作2是将从x到y的花瓶清空掉,输出清空的瓶子的数量。

二分加线段树。首先二分搜索左侧位置,也就是查询的时候空花瓶个数大于等于1的位置,也就是第一个空花瓶的位置,确定了左端点,二分查找右端点。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e4+5;
struct node
{
    int val, lazy, len;
}tree[maxn<<2];
int T, n, m;

void build(int l, int r, int cur)
{
    tree[cur].lazy = -1;
    tree[cur].val = 1;
    tree[cur].len = r-l+1;
    if(l == r)  return ;
    int mid = (l+r)>>1;
    build(l, mid, cur<<1);
    build(mid+1, r, cur<<1|1);
    tree[cur].val = tree[cur<<1].val+tree[cur<<1|1].val;
}

void pushDown(int cur)
{
    if(tree[cur].lazy == -1)    return ;
    tree[cur<<1].lazy = tree[cur<<1|1].lazy = tree[cur].lazy;
    tree[cur<<1].val = tree[cur<<1].len*tree[cur].lazy;
    tree[cur<<1|1].val = tree[cur<<1|1].len*tree[cur].lazy;
    tree[cur].lazy = -1;
}

int query(int L, int R, int l, int r, int cur)
{
    if(L <= l && r <= R)    return tree[cur].val;
    pushDown(cur);
    int mid = (l+r)>>1;
    int sum = 0;
    if(L <= mid)    sum += query(L, R, l, mid, cur<<1);
    if(R > mid) sum += query(L, R, mid+1, r, cur<<1|1);
    return sum;
}

void update(int L, int R, int l, int r, int cur, int val)
{
    if(L <= l && r <= R)
    {
        tree[cur].lazy = val;
        tree[cur].val = tree[cur].len*val;
        return ;
    }
    pushDown(cur);
    int mid = (l+r)>>1;
    if(L <= mid)    update(L, R, l, mid, cur<<1, val);
    if(mid < R) update(L, R, mid+1, r, cur<<1|1, val);
    tree[cur].val = tree[cur<<1].val+tree[cur<<1|1].val;
}

int Find_Left(int l, int r)
{
    int ans = -1;
    int low = l, high = r;
    while(low <= high)
    {
        int mid = (low+high)>>1;
        int temp = query(l, mid, 1, n, 1);
        if(temp >= 1)
        {
            ans = mid;
            high = mid-1;
        }
        else low = mid+1;
    }
    return ans;
}

int Find_Right(int l, int q)
{
    int low = l, high = n;
    int ans = -1;
    int _min = min(q, query(l, n, 1, n, 1));
    while(low <= high)
    {
        int mid = (low+high)>>1;
        int temp = query(l, mid, 1, n, 1);
        if(temp >= _min)    high = mid-1;
        else low = mid+1;
        if(temp == _min)    ans = mid;
    }
    return ans;
}

int main()
{
    cin >> T;
    while(T--)
    {
        scanf("%d%d", &n, &m);
        build(1, n, 1);
        int q, x, y;
        while(m--)
        {
            scanf("%d%d%d", &q, &x, &y);
            if(q == 2)
            {
                x++;    y++;
                printf("%d\n", y-x+1-query(x, y, 1, n, 1));
                update(x, y, 1, n, 1, 1);
            }
            if(q == 1)
            {
                x++;
                if(query(x, n, 1, n, 1) == 0 || y == 0)
                {
                    printf("Can not put any one.\n");
                    continue ;
                }
                int L = Find_Left(x, n);
                int R = Find_Right(L, y);
                printf("%d %d\n", L-1, R-1);
                update(L, R, 1, n, 1, 0);
            }
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40788897/article/details/99358065
今日推荐