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
- HDU 4614 线段树(区间更新)+二分
- hdu-4614-Vases and Flowers(线段树,区间更新区间查询,lazy,二分)
- hdu 4747 Mex(线段树区间更新+二分)
- HDU 4614 Vases and Flowers(线段树区间更新+二分)
- hdu 4614 Vases and Flowers(线段树区间更新+二分)
- HDU 4614 Vases and Flowers (二分查找+线段树区间更新)
- HDU6070(二分+线段树区间更新)
- HDU 2871 Memory Control(线段树区间更新,延迟更新+vector+二分)
- HDU 4893 Wow! Such Sequence! (线段树单点更新+区间更新+区间查询+二分)
- HDU 1698(线段树区间更新)
- HDU 1698(线段树 区间更新)
- HDU 1698(线段树区间更新)
- hdu 3577(线段树区间更新)
- HDU 1698(线段树,区间更新)
- hdu 5023(线段树区间更新+区间查询)
- HDU 4614 Vases and Flowers (线段树[区间赋值+区间求和] + 二分)
- HDU - 4614 Vases and Flowers(线段树 区间修改 二分)
- HDU-4614 Vases and Flowers(线段树+区间修改+二分)
- 可视化CNN
- Unity3d 物体速度快直接穿透墙体没有发生碰撞怎么办?
- CAS 交互流程
- hbase 和 hive 学习
- 计算机网络通讯
- HDU 4614 线段树(区间更新)+二分
- hdu 4635(tarjan)
- 每日MySQL之013:TIMESTAMP和DATETIME列的自动初始化与自动更新
- 秒速五厘米(为情怀而补的题)
- 【扩展欧几里得】poj 1061 青蛙的约会
- 1.Android灯光系统_led_class驱动
- C++ STL之字符串容器string用法详解
- Linux下常见的软件安装方式
- jsp写一个简单的登录界面,有默认值