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 <algorithm>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <list>
#include <iterator>

using namespace std;
#define lson l , mid , rt << 1
#define rson mid + 1 , r , rt << 1 | 1
#define debug(x) cerr << #x << " = " << x << "\n";

typedef long long ll;
const int maxn =  50009;
const int mdd = 10007;
int n,m;
struct node {
    int l,r;
    int lazy,sum;
}st[maxn<<2];

void build(int l,int r,int rt)
{
    st[rt].l = l,st[rt].r = r;
    st[rt].sum = 0;
    st[rt].lazy = -1;
    int mid = (l+r)>>1;
    if(l==r)return;
    build(lson);
    build(rson);
}
inline void pushup(int rt)
{
    st[rt].sum = st[rt<<1].sum + st[rt<<1|1].sum;
}
inline void pushdown(int rt)
{

    if(st[rt].lazy==1)
    {
        st[rt<<1].lazy = st[rt<<1|1].lazy = st[rt].lazy;
        st[rt<<1].sum = st[rt<<1].r - st[rt<<1].l + 1;
        st[rt<<1|1].sum = st[rt<<1|1].r - st[rt<<1|1].l + 1;
    }
    else if(st[rt].lazy==0)
    {
        st[rt<<1].lazy = st[rt<<1|1].lazy = st[rt].lazy;
        st[rt<<1].sum = st[rt<<1|1].sum = 0;
    }

    st[rt].lazy = -1;
}
int  query(int l,int r,int rt,int L,int R)
{
    if(l>=L&&r<=R)
    {
        return st[rt].sum;
    }
    int mid = (l + r)>>1;
    pushdown(rt);
    int ans = 0;
    if(mid>=L)ans += query(l,mid,rt<<1,L,R);
    if(mid<R)ans += query(mid+1,r,rt<<1|1,L,R);
    return ans;
}
void update(int l,int r,int rt,int L,int R,int op)
{
    if(l>=L&&r<=R)
    {
        if(op==1){
            st[rt].lazy = 1;
            st[rt].sum = r - l + 1;
        }
        else {
            st[rt].lazy = 0;
            st[rt].sum = 0;
        }
        return;
    }
    int mid = (r+l)>>1;
    pushdown(rt);
    if(mid>=L)update(l,mid,rt<<1,L,R,op);
    if(mid<R)update(mid+1,r,rt<<1|1,L,R,op);
    pushup(rt);
}
int bdfind(int st,int len)//二分查找
{
    int le = st;
    int ri = n;
    int ans = -1;
    while(le <= ri)
    {
        int mid = (le + ri)>>1;
        int lenSum = query(1,n,1,st,mid);    //找有花的瓶子个数
        if(lenSum + len == mid - st + 1)
        {
            ans =  mid;        //不要直接return,要找最小的。
            ri = mid - 1;
        }
        else if(lenSum + len < mid - st +1)
        {
            ri = mid - 1;
        }
        else le = mid + 1;
    }
    return ans;//找到在【st,mid】间符合len个空瓶;
}
int main(){
    // freopen("input","r",stdin);
     int t;
     scanf("%d", &t);
     while(t--)
     {
         scanf("%d%d", &n, &m);
         build(1,n,1);
         while(m--)
         {
             int op;
             int a,b,c;
             scanf("%d%d%d", & op, & a,& b);
             if(op==1)
             {
                 a++;
                 int st = bdfind(a,1);
                 if(st==-1)
                     puts("Can not put any one.");
                 else
                 {
                     int tmp = query(1,n,1,st,n);
                     tmp = (n - st + 1) - tmp;    //空瓶个数
                     b = min(tmp,b);
                     int ed = bdfind(a, b);
                     printf("%d %d\n",st-1,ed-1);
                     update(1,n,1,st,ed,1);
                 }
             }
             else
             {
                 a++,b++;
                 printf("%d\n",query(1,n,1,a,b));
                 update(1,n,1,a,b,0);
             }
         }
         puts("");
     }
    return 0;
}

原文地址:https://www.cnblogs.com/ckxkexing/p/9021564.html

时间: 2024-10-04 21:36:35

HDU4614Vases and Flowers 二分+线段树;的相关文章

【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

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

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

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

【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

计蒜客16492 building(二分线段树/分块)

题解: 考虑用线段树维护楼的最大值,然后这个问题就很简单了. 每次可以向左二分出比x高的第一个楼a,同理也可以向右二分出另一个楼b,如果a,b都存在,答案就是b-a-1. 注意到二分是可以直接在线段树上进行的,所以复杂度是O(nlogn). 当然这里是用分块做的,更暴力一些. #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace st