HDOJ 4614 Vases and Flowers

线段树+二分区间

用线段树维护某一段内还有多少个花瓶可以用,二分确定插入的左右界.....

Vases and Flowers

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)

Total Submission(s): 1782    Accepted Submission(s): 700

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

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]

Source

2013 Multi-University Training Contest 2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int maxn=60050;
int sum[maxn<<2],col[maxn<<2];
int n,m,leftbound,rightbound,F,A,B;

void init()
{
    memset(sum,0,sizeof(sum));
    memset(col,-1,sizeof(col));
}

void push_up(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}

void build(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=1; return ;
    }
    int m=(l+r)/2;
    build(lson); build(rson);
    push_up(rt);
}

void push_down(int len,int rt)
{
    if(col[rt]!=-1)
    {
        col[rt<<1]=col[rt<<1|1]=col[rt];
        sum[rt<<1]=(len-len/2)*col[rt];
        sum[rt<<1|1]=(len/2)*col[rt];
        col[rt]=-1;
    }
}

int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
        return sum[rt];
    push_down(r-l+1,rt);
    int m=(l+r)/2;
    int ret=0;
    if(L<=m) ret+=query(L,R,lson);
    if(R>m) ret+=query(L,R,rson);
    return ret;
}

void Update(int L,int R,int c,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        col[rt]=c;
        sum[rt]=(r-l+1)*c;
        return ;
    }
    push_down(r-l+1,rt);
    int m=(l+r)/2;
    if(L<=m) Update(L,R,c,lson);
    if(R>m) Update(L,R,c,rson);
    push_up(rt);
}

void showit(int l,int r,int rt)
{
    cout<<"rt: "<<rt<<" left "<<l<<" right "<<r<<" sum "<<sum[rt]<<" col: "<<col[rt]<<endl;
    if(l>=r) return ;
    int m=(l+r)/2;
    showit(lson);showit(rson);
}

int get_left_point(int x)
{
    int ans=-1;
    int low=x,high=n,mid;
    int w;
    while(low<=high)
    {
        mid=(low+high)/2;
        w=query(x,mid,1,n,1);
        if(!w) low=mid+1;
        else ans=mid,high=mid-1;
    }
    return ans;
}

int get_right_point()
{
    int ans=-1;
    int low=leftbound,high=n,mid;
    int w;
    B=min(B,query(low,n,1,n,1));
    while(low<=high)
    {
        mid=(low+high)/2;
        w=query(leftbound,mid,1,n,1);
        if(w>=B) high=mid-1;
        else low=mid+1;
        if(w==B) ans=mid;
    }
    return ans;
}

int main()
{
    int T_T;
    scanf("%d",&T_T);
    while(T_T--)
    {
        scanf("%d%d",&n,&m);
        init();
        build(1,n,1);
        while(m--)
        {
            scanf("%d%d%d",&F,&A,&B);
            A++;
            if(F==1)
            {
                if(!query(A,n,1,n,1)||B==0)
                {
                    puts("Can not put any one.");
                    continue;
                }
                leftbound=get_left_point(A);
                rightbound=get_right_point();
                printf("%d %d\n",leftbound-1,rightbound-1);
                Update(leftbound,rightbound,0,1,n,1);
            }
            else if(F==2)
            {
                B++;
                printf("%d\n",B-A+1-query(A,B,1,n,1));
                Update(A,B,1,1,n,1);
            }
        }
        putchar(10);
    }
    return 0;
}

HDOJ 4614 Vases and Flowers,码迷,mamicode.com

时间: 2024-10-24 07:31:08

HDOJ 4614 Vases and Flowers的相关文章

hdu 4614 Vases and Flowers

http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意:有N个花瓶,标号为0-N-1,往每一个花瓶放一朵花,然后有M个操作,输入a,b,c,如果a==1表示从b开始放花,期间有花就跳过,直到结束,如果没有放入一朵花,则输出“Can not put any one.”,否则输入第一朵花放的位置和最后一朵花放的位置. 如果a==2 则输出拔掉的花的朵数. 1 #include <cstdio> 2 #include <cstring> 3 #

HDU 4614 Vases and Flowers 线段树+二分

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意:N个花瓶,两种操作. 操作1:从第a个花瓶开始放花,放最多f个,如果花瓶已经有花就跳过,直到放完,或者无更多花瓶,要求输出这次放花的第一个位置和最后一个位置,如果没放就输出Cannot... 操作2:将花瓶a到b区间内的花都扔了,然后输出扔掉的花的数目. 解题思路:花瓶有花为0,无花为1,那么实际上这是一个区间更新以及求和,求左右端点的问题.线段树节点维护一个 sum--区间和,lid-

HDU 4614 Vases and Flowers(线段树区间更新+二分)

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 a

hdu4614 Vases and Flowers

Vases and Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 2148    Accepted Submission(s): 836 Problem Description Alice is so popular that she can receive many flowers everyday. She has

L - Vases and Flowers - hdu 4614(区间操作)

题意:有两种操作,第一种从A开始插花,如果有花就跳到下一个,然后输出最后一个花瓶的编号,如果花瓶不够把多余的花丢掉.操作2把区间清空 分析:很明显的线段树操作,就是插花的时候麻烦一下,需要先找出来他剩余的花瓶数,要不没办法更新. ******************************************************************* #include<algorithm>#include<stdio.h>using namespace std; #de

【HDU 4614】Vases and Flowers(线段树区间更新懒惰标记)

题目0到n-1的花瓶,操作1在下标a开始插b朵花,输出始末下标.操作2清空[a,b]的花瓶,求清除的花的数量.线段树懒惰标记来更新区间.操作1,先查询0到a-1有num个空瓶子,然后用线段树的性质,或者二分找出第num+1个空瓶子的下标,和第num+b个空瓶子的下标.再区间更新为满.操作2,也相当于区间更新为空. #include<cstdio> #include<cstring> #include<algorithm> #define N 50001 using na

【HDU-4614】Vases and Flowers(线段树双查询)

11946317 2014-10-23 09:08:28 Accepted 4614 437MS 2348K rid=11946317" target="_blank" style="color:rgb(26,92,200); text-decoration:none">3340 B G++ KinderRiven #include<cstdio> #include<cstring> #include<iostream&

Vases and Flowers

hdu4614:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意:给你n个花瓶,然后有两种操作:1从a开始选择b个花瓶,放进花,输出左端点,右端点 2把a到b之间的花瓶中的花拿走,输出拿走的花的数目. 题解:一看数据范围就知道是线段树,sum维护区间空的花瓶的个数,flag作为lazy标记,如果flag==1表示清空,flag==0表示填满.这一题重要的地方就是二分. 二分找左边的端点,二分找右边的端点.这是这一题的关键,复杂度就是M*logN*

HDU-4614 Vases and Flowers (线段树区间更新)

题目大意:有n个花瓶,每个花瓶中只能放一朵花.两种操作,一种是从A开始放F朵花,如果有的花瓶中已经有花则跳过这个花瓶,往下一个花瓶放:第二种是将区间[A,B]之间花瓶中的花清空.如果是第一种操作,输出这次放的花的左右端点:如果是第二种操作,输出这次总共清理出了多少支花. 题目分析:建立线段树,节点维护在相应的区间中,没有放入花的花瓶数目.有三种操作:一.查询某个区间中第k个没有插入花的花瓶位置:二.更新区间,使区间全部插入花:三.更新区间,使区间中的花瓶全部清空: 代码如下: # include