HDU 4614 线段树(区间更新)+二分

来源:互联网 发布:最近的网络流行词 编辑:程序博客网 时间:2024/05/21 10:05

题意

有0-N-1个花瓶,两种操作。一种操作是从某个点开始,放F朵花,如果一朵花都不能放,则输出“Can not put any one.”,否则输出放花的区间。另一种操作是清理A到B区间内的所有花,输出清理的数量。

题解

感觉这道题还是有一些难度的,主要是要对题意有着比较深刻的理解。题目最坑的地方在于,可以放0朵花。更坑的是,放0朵花的话,比如在X点放0朵花,那么X点就会变成没有花的点。。。因此更新的时候,0也是要更新的,于是setv数组默认值就不能是0。。。
除了题意的难度以外,二分的使用上也还是有一定难度的。要准确的二分出放花的区间还是很困难的。最重要的一点就是要想到放花并不一定能放完所有的花,所以需要计算能放多少花,然后根据这个数量再进行二分,这样的话才能求出来右边界。左边界的求取也要一定的技巧,技巧就是如果从左边界开始向右的一个区
间内已经塞满了花,则区间右边界右移。最后放花的开始位置就是右边界。

注意事项

这道题题意难,想法难,实现也比较难。涉及到区间更新和区间查询,算是比较难的一种线段树,很容易写错。我在写的时候就犯了忘记maintain(pushup)的错误。update()的时候需要pushdown和maintain,query的时候也需要pushdown和maintain。少一句话都是不行的。

代码

#include <iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<string>#include<set>#include<map>#include<bitset>#include<stack>#define UP(i,l,h) for(int i=l;i<h;i++)#define DOWN(i,h,l) for(int i=h-1;i>=l;i--)#define W(a) while(a)#define MEM(a,b) memset(a,b,sizeof(a))#define INF 0x3f3f3f3f3f3f3f3f#define LL long long#define MAXN 50010#define SIZE 95#define EPS 1e-10#define MOD 1000000007using namespace std;int n,m;int lt,rt,v;    int setv[MAXN<<2],num[MAXN<<2];void pushdown(int o,int l,int r,int m) {    if(setv[o]!=-1){        setv[o*2]=setv[o*2+1]=setv[o];    }    setv[o]=-1;}void maintain(int o,int l,int r){    if(l<r){        num[o]=num[o*2]+num[o*2+1];    }    if(setv[o]!=-1){        num[o]=setv[o]*(r-l+1);    }}void update(int o,int l,int r) {    if(lt<=l&&rt>=r) {        setv[o]=v;        num[o]=v*(r-l+1);    } else {        int m=l+(r-l)/2;        pushdown(o,l,r,m);        if(lt<=m) {            update(o*2,l,m);        }else{            maintain(o*2,l,m);        }        if(rt>m) {            update(o*2+1,m+1,r);        }else{            maintain(o*2+1,m+1,r);        }        maintain(o,l,r);    }}int query(int o,int l,int r) {    maintain(o,l,r);    if(lt<=l&&rt>=r) {        return num[o];    } else {        int m=l+(r-l)/2;        pushdown(o,l,r,m);        int ans=0;        if(lt<=m) {            ans+=query(o*2,l,m);        }else{            maintain(o*2,l,m);        }        if(rt>m) {            ans+=query(o*2+1,m+1,r);        }else{            maintain(o*2+1,m+1,r);        }        maintain(o,l,r);        return ans;    }}int main() {    int t;    scanf("%d",&t);    W(t--) {        scanf("%d%d",&n,&m);        MEM(setv,-1);        MEM(num,0);        UP(i,0,m) {            int k,a,b;            scanf("%d%d%d",&k,&a,&b);            if(k==1) {                a++;                lt=a,rt=n;                int now=query(1,1,n);                b=min(b,(rt-lt+1)-now);                if(b<=0) {                    puts("Can not put any one.");                } else {                    int low=lt,high=rt;                    int temp=a-1;                    W(low<=high) {                        int mid=(low+high)/2;                        lt=a,rt=mid;                        int len=query(1,1,n);                        if(((rt-lt+1)==len)) {                            temp=mid;                            low=mid+1;                        } else {                            high=mid-1;                        }                    }                    a=temp+1;                    temp=n;                    low=a,high=n;                    W(low<=high) {                        int mid=(low+high)/2;                        lt=a,rt=mid;                        int len=query(1,1,n);                        if((rt-lt+1-len)>=b) {                            temp=mid;                            high=mid-1;                        } else {                            low=mid+1;                        }                    }                    lt=a;                    rt=temp;                    v=1;                    update(1,1,n);                    printf("%d %d\n",lt-1,rt-1);                }            } else {                lt=a+1;                rt=b+1;                v=0;                int len=query(1,1,n);                update(1,1,n);                printf("%d\n",len);            }        }        puts("");    }}
阅读全文
0 0
原创粉丝点击