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;
}

 

posted @ 2018-05-10 20:27  ckxkexing  阅读(124)  评论(0编辑  收藏  举报