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

题意:

n个花瓶,m个操作,花瓶里面有的有花,有的是空的。1操作是从a开始往右放b朵花,花瓶有了的不放,跳过,直到a右边都放满了花,多余的扔了。输出本次放花的起始位置,如果一朵不能放,输出一句话。

分析:

如果知道了区间的开始和结束位置的话,那么这道题就是非常简单的线段树了,那么重点就是怎么计算区间的开始和结束位置呢,因为题目给的是开始位置和往后放几个花的数量,那么就可以二分查找开始放的空位和结束放的空位,

#include<bits/stdc++.h>

using namespace std;

const int maxn=5e4+10;

struct node{
    int sum;
    int mark;
}tree[maxn<<2];

int n,m;

void build(int l,int r,int i){
    tree[i].sum=0;
    tree[i].mark=-1;
    if(l==r) return;
    int mid=l+r>>1;
    build(l,mid,i<<1);
    build(mid+1,r,i<<1|1);
}

void update(int l,int r,int i){
    if(tree[i].mark==-1) return;
    int mid=l+r>>1;
    if(tree[i].mark==1){
        tree[i<<1].sum=mid-l+1;
        tree[i<<1|1].sum=r-mid;
        tree[i<<1].mark=tree[i<<1|1].mark=1;
    }else{
        tree[i<<1].sum=tree[i<<1|1].sum=tree[i<<1].mark=tree[i<<1|1].mark=0;
    }
    tree[i].mark=-1;
}

int query(int tl,int tr,int l,int r,int i){
    if(tl>r||tr<l) return 0;
    if(tl<=l&&r<=tr){
        return tree[i].sum;
    }
    update(l,r,i);
    int mid=l+r>>1;
    return query(tl,tr,l,mid,i<<1)+query(tl,tr,mid+1,r,i<<1|1);
}

void change(int tl,int tr,int l,int r,int i,int flag){
    if(tl>r||tr<l) return;
    if(tl<=l&&r<=tr){
        if(flag){
            tree[i].sum=r-l+1;
            tree[i].mark=1;
        }else{
            tree[i].sum=0;
            tree[i].mark=0;
        }
        return;
    }
    update(l,r,i);
    int mid=l+r>>1;
    change(tl,tr,l,mid,i<<1,flag);
    change(tl,tr,mid+1,r,i<<1|1,flag);
    tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}

int bin_search(int st,int x){
    int l=st,r=n,ans=-1;
    while(l<=r){
        int mid=l+r>>1;
        int tmp=query(st,mid,1,n,1);
        if(tmp+x==mid-st+1){
            ans=mid;
            r=mid-1;
        }else{
            if(tmp+x>mid-st+1){
                l=mid+1;
            }else r=mid-1;
        }
    }
    return ans;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while(m--){
            int f,l,r;
            scanf("%d%d%d",&f,&l,&r);
            if(f==1){
                l++;
                l=bin_search(l,1);
                if(l==-1){
                    printf("Can not put any one.\n");
                }else{
                    int tmp=query(l,n,1,n,1);
                    tmp=n-l+1-tmp;
                    if(tmp<=r) r=tmp;
                    r=bin_search(l,r);
                    printf("%d %d\n",l-1,r-1);
                    change(l,r,1,n,1,1);
                }
            }else{
                l++,r++;
                printf("%d\n",query(l,r,1,n,1));
                change(l,r,1,n,1,0);
            }
        }
        puts("");
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40679299/article/details/83215335