hdu 4614 线段树 二分

Posted wjhstudy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4614 线段树 二分相关的知识,希望对你有一定的参考价值。

题意:有n个花瓶,每个花瓶中只能放一朵花。

两种操作,一种是从A开始放F朵花,如果有的花瓶中已经有花则跳过这个花瓶,往下一个花瓶放;

    输出这次放的花的左右端点。如果能放但是放不完f朵输出n就好了

第二种是将区间[A,B]之间花瓶中的花清空。输出这次总共清理出了多少支花。

 

思路:第二种很明显可以用线段树实现,问题在第一种如何用线段树实现

  用二分  和 线段树 来判断右端点的位置  这样就可以了  第一次操作就成了区间更新

  并且查询左右端点

 

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;

#define ll long long
#define pb push_back
#define mp make_pair
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define fi first
#define se second
const int N = 5E4+3;
const int M  = 5e4+3;

int n,m;
int sum[N<<2],fst[N<<2],las[N<<2],L[N<<2],R[N<<2];
int col[N<<2];
//fst 开始空的  las最后空的  sum 空的数量
void pushup(int rt){
    sum[rt] = sum[rt<<1]+sum[rt<<1|1];
    if(las[rt<<1|1]!=-1)
        las[rt]=las[rt<<1|1];
    else las[rt]=las[rt<<1];
    if(fst[rt<<1]!=-1)
        fst[rt]=fst[rt<<1];
    else fst[rt] = fst[rt<<1|1];
    R[rt] = R[rt<<1|1];
    L[rt] = L[rt<<1];
}

void pushdown(int rt){
    //添加
    if(col[rt]==1){
        col[rt<<1]=col[rt<<1|1] = col[rt];
        sum[rt<<1]  = 0;
        sum[rt<<1|1] = 0;
        las[rt<<1]=las[rt<<1|1] = -1;
        fst[rt<<1]=fst[rt<<1|1] =-1;
        col[rt]=0;
    }
    else if(col[rt]==-1){
        col[rt<<1]=col[rt<<1|1] = col[rt];
        sum[rt<<1] = R[rt<<1]-L[rt<<1]+1;
        sum[rt<<1|1] = R[rt<<1|1]-L[rt<<1|1]+1;
        las[rt<<1] = R[rt<<1];
        fst[rt<<1] = L[rt<<1];
        las[rt<<1|1] = R[rt<<1|1];
        fst[rt<<1|1] = L[rt<<1|1];
        col[rt]=0;
    }
}

void build(int l,int r,int rt){
    col[rt] =0;
    if(l==r){
        L[rt] = r;
        R[rt] = l;
        sum[rt]=1;
        las[rt]=r;
        fst[rt]=l;
        return ;
    }
    int mid = (l+r)/2;
    build(lson);build(rson);
    pushup(rt);
}

void update(int l,int r,int rt, int a,int b,int val){

    if(a<=l && b>=r){

        if(val==1){
           if(sum[rt] ==0)return;
            col[rt] = val;
            sum[rt] = 0;
            las[rt]=fst[rt]=-1;
        }
        else if(val==-1){
            if(sum[rt]==R[rt]-L[rt]+1)return;
          // printf("%d %d %d %d %d %d
",l,r,rt,a,b,sum[rt]);
            col[rt]=val;
            sum[rt]= R[rt]-L[rt]+1;
            las[rt]=R[rt];
            fst[rt]=L[rt];
           // printf("gai: %d %d %d %d %d %d
",l,r,rt,a,b,sum[rt]);
        }
        return ;
    }

    pushdown(rt);

     int mid=(l+r)/2;
     if( a<=mid ) update(lson,a,b,val);
     if( b>mid ) update(rson ,a,b,val);
     pushup( rt );

}

int qfst(int l,int r,int rt,int a,int b){
    if(a<=l && b>=r){
        return fst[rt];
    }
    pushdown(rt);
    int mid =(l+r)/2;
    if(b<=mid)return qfst(lson,a,b);
    else if( a>mid )return qfst(rson,a,b);
    else {
        int ans1=-1;
        if(a<=mid)
            ans1 = qfst(lson,a,b);
        if(ans1!=-1)return ans1;
        if(b>mid)
        return qfst(rson,a,b);
    }
}

int qlst(int l,int r,int rt,int a,int b){
     if(a<=l && b>=r){
        return las[rt];
    }
     pushdown(rt);
    int mid =(l+r)/2;
    if(b<=mid)return qlst(lson,a,b);
    else if(a>mid)return qlst(rson,a,b);
    else {
        int ans1=-1;
        if(b>mid)
            ans1= qlst(rson,a,b);
        if(ans1!=-1)return ans1;
        if(a<=mid)return qlst(lson,a,b);
    }
}

int qnum(int l,int r,int rt,int a,int b){
    if(a<=l && b>=r){
        //printf("get :%d %d %d %d %d %d
",l,r,rt,a,b,sum[rt]);
        int res = sum[rt];
        return res;
    }
    pushdown(rt);
    int ans = 0;
    int mid =(l+r)/2;
    if(a<=mid)
        ans+=qnum(lson,a,b);
    if(b>mid)
        ans+=qnum(rson,a,b);
    return ans;
}

int b_s(int st,int need){

    int l=st,r=n;
    int res = qnum(1,n,1,st,n);
    if(res==0)return -1;
    if(res<need)return n;
    int ans = n;
    while(l<=r){
        int m = (l+r)/2;
        if(qnum(1,n,1,st,m)>=need){
            ans = min(ans,m);
            r=m-1;
        }
        else l= m+1;
    }
    return ans;
}

int main(){

    int t;
    cin>>t;
    int op;
    while(t--){
        scanf("%d %d",&n,&m);

        build(1,n,1);

        while(m--){
            scanf("%d",&op);
            if(op==1){
                int x,f;scanf("%d %d",&x,&f);
                x++;
                int v = b_s(x,f);
                if(v==-1){
                    printf("Can not put any one.
");
                }
                else {
                    printf("%d %d
",qfst(1,n,1,x,v)-1 ,qlst(1,n,1,x,v)-1);
                    update(1,n,1,x,v,1);
                }
            }
            else if(op==2){
                int a,b;scanf("%d %d",&a,&b);
                a++;b++;
                int res = qnum(1,n,1,a,b);
                printf("%d
",b-a+1-res);
                update(1,n,1,a,b,-1);
              //  cout<<sum[24]<<"!!"<<endl;
                res = qnum(1,n,1,a,b);
              // printf("update : %d
",b-a+1-res);
            }
        }
        cout<<endl;
    }
    return 0;
}

 

以上是关于hdu 4614 线段树 二分的主要内容,如果未能解决你的问题,请参考以下文章

hdu 4614 线段树 二分

HDU4614Vases and Flowers 二分+线段树;

HDU 4614 Vases and Flowers 线段树+二分

Vases and Flowers HDU - 4614线段树+主席树思维/二分

L - Vases and Flowers HDU - 4614 线段树+二分

Vases and Flowers-HDU4614 二分+线段树