Vases and Flowers-HDU4614 二分+线段树

题意:

给你N个花瓶,编号是0  到 N - 1 ,一开始每个花瓶都是空的,你有两个操作:

第一个操作:

从第x个花瓶起开始插花,总共插y束,如果遇到花瓶中有花就跳过这个花瓶,直到花插完或者

插到第N-1个花瓶为止,输出插第一朵花的位置和最后一朵花的位置

第二个操作

将第x个花瓶到第y个花瓶之间的花扔掉,输出扔掉的花的数目

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614

思路

我们通过线段树来记录每个区间中花的数目,区间长度减去该区间中花的数目即为该区间

中空花瓶的数目,我们通过二分位置来确定插花的起始位置和终止位置

代码:

#include <bits/stdc++.h>
int n,m;
using namespace std;
const int MAXN=5e4+4;
typedef long long ll;
int lazy[MAXN<<4],tree[MAXN<<4];
void push_up(int node)
{
    tree[node]=tree[node<<1]+tree[node<<1|1];
}
void build(int node,int l,int r)
{
    lazy[node]=-1,tree[node]=0;
    if(l==r)
        return;
    int mid=(l+r)>>1;
    build(node<<1,l,mid);
    build(node<<1|1,mid+1,r);
}
void push_down(int node,int l,int r,int mid)
{
    if(lazy[node]!=-1)
    {
        lazy[node<<1]=lazy[node<<1|1]=lazy[node];
        tree[node<<1]=(mid-l+1)*lazy[node];
        tree[node<<1|1]=(r-mid)*lazy[node];
        lazy[node]=-1;
    }
}
void update(int node,int l,int r,int x,int y,int k)
{
    if(x<=l&&y>=r)
    {
        lazy[node]=k;
        tree[node]=(r-l+1)*k;
        return;
    }
    int mid=(l+r)>>1;
    push_down(node,l,r,mid);
    if(x<=mid)
        update(node<<1,l,mid,x,y,k);
    if(y>mid)
        update(node<<1|1,mid+1,r,x,y,k);
    push_up(node);
}
int query(int node,int l,int r,int x,int y)
{
    if(x<=l&&y>=r)
    {
        return tree[node];
    }
    int mid=(l+r)>>1;
    push_down(node,l,r,mid);
    int ans=0;
    if(x<=mid)
        ans+=query(node<<1,l,mid,x,y);
    if(y>mid)
        ans+=query(node<<1|1,mid+1,r,x,y);
    return ans;
}
int search_(int x,int num)  //二分查找位置
{
    int temp=query(1,0,n,x,n);//x到n的空位数
    if(temp==n-x+1)//没有空位的情况下
        return -1;
    //如果从x到n的空位数比要插的数少,那么要插的数就是x到n的空位数
    if(n-x+1-temp<num)
        num=n-x+1-temp;
    int down=x,up=n,index=0;
    while(down<=up)
    {
        int mid=(down+up)>>1;
        if(mid-x+1-query(1,0,n,x,mid)<num)
            down=mid+1;
        else
            if(mid-x+1-query(1,0,n,x,mid)>num)
            up=mid-1;
        else
        {
            index=mid;up=mid-1;
        }
    }
    return index;
}
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);n--;
        build(1,0,n);
        while(m--)
        {
            int op,x,y;
            scanf("%d%d%d",&op,&x,&y);
            if(op==1)
            {
                int fir=search_(x,1);//寻找第一个位置
                if(fir==-1)
                    printf("Can not put any one.\n");
                else
                {
                    int sec=search_(x,y);//寻找第二个位置
                    printf("%d %d\n",fir,sec);
                    update(1,0,n,fir,sec,1);//修改区间值
                }
            }
            else
            {
                printf("%d\n",query(1,0,n,x,y));
                update(1,0,n,x,y,0);//修改区间值
            }
        }
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ljxdtc666/p/12235841.html

时间: 2024-10-10 19:37:58

Vases and Flowers-HDU4614 二分+线段树的相关文章

Vases and Flowers (二分 + 线段树)

题目链接:https://vjudge.net/contest/332656#problem/H 题意: n个花瓶,m个操作,花瓶里面有的有花,有的是空的. 1 x y 表示从第x个位置开始查y多花,若一朵花也插不上输出"Can not put any one.",反之输出插花的左位置和右位置. 2 操作是清除区间[a,b]的花.并输出清除了多少花. 思路:线段树维护区间,然后每次二分查找满足要求的第一个位置. 1 #include <math.h> 2 #include

hdu4614 二分+线段树

题意:给你1-n的花瓶   ,刚开始全是空的,现在有两种操作, 1:从花瓶a开始插入b朵花          如果不能插进去  输出字符串  否则输出最多插入的起点和终点: 2:把a-b的花瓶清空   输出处理花的个数: 结构体数组num[i]表示节点i空瓶的数目 线段树   开始deal函数对整个树初始化,update()更新函数 find()查询区间有多少个空瓶:     对于操作1    关键点是找到起点和终点   这里用二分  在[a,n]进行二分, 先二分起点       注意左右区间

【BZOJ-3110】K大数查询 整体二分 + 线段树

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Status][Discuss] Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M接下来M行,每行形如1 a

hdu4614(线段树+二分)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意:给定一个区间[0,N-1],初始时每个位置上的数字都是0,可以对其进行以下两种操作: 1.在位置A开始寻找F(如果没有这么多,则有多少个就找多少个)个数值为0的位置,把位置上的数修改为1,并返回第一个和最后一个修改的位置 2.查询区间[a,b]内1的个数,并把区间[a,b]每个位置上的数修改为0 线段树功能:区间更替,区间求和. 分析:sum[rt]表示区间0的个数,二分找出0~L的nu

HDU4614Vases and Flowers 二分+线段树;

参考:https://blog.csdn.net/ophunter_lcm/article/details/9879495 题意: 有n个花瓶,有两种操作,1.从a开始放b朵花,有花的花瓶跳过,2.把a到b间的花全部拿下来. 思路: 线段树+二分 利用二分确定区间,这样就可以是线段树实现更简单的问题: 1)对区间进行全部设置为1的操作 2)对区间进行全部清零的操作 #include <iostream> #include <cstdio> #include <algorith

HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)

题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5008 Description In this problem, you are given a string s and q queries. For each query, you should answer that when all distinct substrings of string s were sorted lexicographically, which one is

(困难) CF 484E Sign on Fence,整体二分+线段树

Bizon the Champion has recently finished painting his wood fence. The fence consists of a sequence of n panels of 1 meter width and of arbitrary height. The i-th panel's height is hi meters. The adjacent planks follow without a gap between them. Afte

zoj 3888 Twelves Monkeys 二分+线段树维护次小值

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3888 Twelves Monkeys Time Limit: 5 Seconds      Memory Limit: 32768 KB James Cole is a convicted criminal living beneath a post-apocalyptic Philadelphia. Many years ago, the Earth's surf

bzoj1568: [JSOI2008]Blue Mary开公司 三分+二分+线段树

答案序列一定是个下凸壳,因此添加的等差数列与其之差是个单峰函数,可以先三分求出最值,再二分求出零点,然后用线段树,将得到的区间修改为一个等差数列. 这个做法应该比较好想吧,虽然比较慢…… #include<cstdio> #define Z int l=1,int r=N,int k=1 #define N 50000 #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define K l,r,k