HDU - 4614 Vases and Flowers —— 线段树 二分

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Lngxling/article/details/81253659

Vases and Flowers

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 4540    Accepted Submission(s): 1866


 

Problem Description

  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.

 

 

Input

  The first line contains an integer T, indicating the number of test cases.
  For each test case, the first line contains two integers N(1 < N < 50001) and M(1 < M < 50001). N is the number of vases, and M is the operations of Alice. Each of the next M lines contains three integers. The first integer of one line is K(1 or 2). If K is 1, then two integers A and F follow. It means Alice receive F flowers and try to put a flower in the vase A first. If K is 2, then two integers A and B follow. It means the owner would like to clean the vases numbered from A to B(A <= B).

 

 

Output

  For each operation of which K is 1, output the position of the vase in which Alice put the first flower and last one, separated by a blank. If she can not put any one, then output 'Can not put any one.'. For each operation of which K is 2, output the number of discarded flowers. 
  Output one blank line after each test case.

 

 

Sample Input

 

2 10 5 1 3 5 2 4 5 1 1 8 2 3 6 1 8 8 10 6 1 2 5 2 3 4 1 0 8 2 2 5 1 4 4 1 2 3

扫描二维码关注公众号,回复: 2971727 查看本文章

 

 

Sample Output

 

[pre]3 7 2 1 9 4 Can not put any one. 2 6 2 0 9 4 4 5 2 3 [/pre]

题意:

有n个花瓶,每次进行1操作会把f朵花从a花瓶开始依次插入空花瓶,剩余的扔掉,输出插入的第一个花瓶和最后一个花瓶的编号,进行2操作会把l到r区间的花瓶全部清空,输出拿出的花的个数。

思路:

线段树维护每段区间的花的数量

进行1操作时,二分a到n,查询剩余花瓶的数量,找到区间后更新(也可以不二分但是写出来的查询函数比较麻烦)

进行2操作时,先区间查询再区间更新

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <cmath>
#include <vector>
#include <bitset>
#define max_ 50101
#define inf 0x3f3f3f3f
#define ll long long
#define les 1e-8
#define mod 364875103
using namespace std;
struct node
{
    int l,r;
    int w;
    int lazy;
};
struct node tree[max_*4];
int n,m;
void built(int i,int l,int r)
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].w=0;
    tree[i].lazy=0;
    if(l==r)
    return;
    int mid=(l+r)>>1;
    built(i<<1,l,mid);
    built(i<<1|1,mid+1,r);
}
void down(int i)
{
    if(tree[i].lazy)
    {
        tree[i<<1].lazy=tree[i<<1|1].lazy=1;
        if(tree[i].w==0)
        tree[i<<1].w=tree[i<<1|1].w=0;
        else
        {
            tree[i<<1].w=(tree[i<<1].r-tree[i].l+1);
            tree[i<<1|1].w=(tree[i<<1|1].r-tree[i<<1|1].l+1);
        }
        tree[i].lazy=0;
    }
}
void updata(int i,int l,int r,int v)
{
    if(tree[i].l==l&&tree[i].r==r)
    {
        tree[i].lazy=1;
        tree[i].w=v*(r-l+1);
        return;
    }
    down(i);
    int mid=(tree[i].l+tree[i].r)>>1;
    if(r<=mid)
    updata(i<<1,l,r,v);
    else if(l>mid)
    updata(i<<1|1,l,r,v);
    else
    {
        updata(i<<1,l,mid,v);
        updata(i<<1|1,mid+1,r,v);
    }
    tree[i].w=tree[i<<1].w+tree[i<<1|1].w;
}
int query(int i,int l,int r)
{
    if(tree[i].l==l&&tree[i].r==r)
    {
        return tree[i].w;
    }
    down(i);
    int mid=(tree[i].l+tree[i].r)>>1;
    if(r<=mid)
    return query(i<<1,l,r);
    else if(l>mid)
    return query(i<<1|1,l,r);
    else
    return query(i<<1,l,mid)+query(i<<1|1,mid+1,r);
}
int finds(int s)
{
    int l=s,r=n;
    int ans=-1;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        int q=query(1,l,mid);
        if(q==mid-l+1)
        {
            l=mid+1;
        }
        else
        {
            ans=mid;
            r=mid-1;
        }
    }
    return ans;
}
int finde(int s,int num)
{
    int l=s,r=n;
    int ans=-1;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        int q=mid-s+1-query(1,s,mid);
        if(q<num)
        {
            l=mid+1;
        }
        else if(q>=num)
        {
            ans=mid;
            r=mid-1;
        }
    }
    return ans;
}
int main(int argc, char const *argv[]) {
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        built(1,1,n);
        while(m--)
        {
            int k,l,r;
            scanf("%d%d%d",&k,&l,&r);
            if(k==1)
            {
                l++;
                int s=finds(l);
                if(s==-1)
                {
                    printf("Can not put any one.\n" );
                    continue;
                }
                int maxx=n-s+1-query(1,s,n);
                if(r>maxx)
                r=maxx;
                int e=finde(s,r);
                printf("%d %d\n",s-1,e-1);
                updata(1,s,e,1);
            }
            else
            {
                l++;r++;
                printf("%d\n",query(1,l,r));
                updata(1,l,r,0);
            }
        }
        printf("\n" );
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Lngxling/article/details/81253659
今日推荐