题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614

题意:

给你N个花瓶,编号是0  到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花。

然后有2个操作。

操作1,a b c ,往在a位置后面(包括a)插b朵花,输出插入的首位置和末位置。

操作2,a b ,输出区间[a , b ]范围内的花的数量,然后全部清空。

很显然这是一道线段树。区间更新,区间求和,

操作2,很显然就是线段树的区间求和,求出[a , b]范围内的花朵的数量,区间更新,将整个区间全部变成0。

操作1,这里我们首先需要找出他的首位置和末位置,所以需要二分他的位置。

首先我们二分他的首位置, l = a , r = n ,在这个区间内二分,找出第一个0的位置,那就是该操作的首位置pos1。

然后再二分他的末位置,l = pos1 , r = n ,找到第b个0,就是该操作的末位置pos2,然后区间更新[pos1 ,pos2]全部置为1

我最初主要是对二分不熟悉,做了几道二分的题目后再做这道题就很快了。。。。

很裸的一道线段树了,一定要用lazy思想设置flag标记位,不能更新到低,否则会超时的。。。。

代码:

 #include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define maxn 50010
int n,m;
class node
{
public:
int l;
int r;
int sum;
int flag;
};
node segTree[maxn*];
void Build(int num, int l, int r)
{
segTree[num].l=l;
segTree[num].r=r;
segTree[num].sum=;
segTree[num].flag=;
if(l==r) return;
int mid=(l+r)/;
Build(num*,l,mid);
Build(num*+,mid+,r);
}
int query(int num, int l, int r)
{
if(segTree[num].l ==l && segTree[num].r==r)
{
return segTree[num].sum;
}
int mid=(segTree[num].l + segTree[num].r)/;
if(segTree[num].flag==)
{
segTree[num*].sum=(segTree[num*].r - segTree[num*].l +);
segTree[num*+].sum=(segTree[num*+].r- segTree[num*+].l +);
segTree[num*].flag=;
segTree[num*+].flag=;
segTree[num].flag=;
}
if(segTree[num].flag ==-)
{
segTree[num*].sum=segTree[num*+].sum=;
segTree[num*].flag=segTree[num*+].flag=-;
segTree[num].flag=;
}
if(r <=mid) return query(num*,l,r);
else if(l >mid ) return query(num*+,l,r);
else
{
return query(num*,l,mid)+query(num*+,mid+,r);
}
}
void Update1(int num,int l, int r)
{
if(segTree[num].flag==) return;
if(segTree[num].l ==l && segTree[num].r==r)
{
segTree[num].sum=r-l+;
segTree[num].flag=;
return ;
}
int mid=(segTree[num].l + segTree[num].r)/;
if(segTree[num].flag==-)
{
segTree[num*].sum=segTree[num*+].sum=;
segTree[num*].flag=segTree[num*+].flag=-;
segTree[num].flag=;
}
if(r<=mid) Update1(num*,l,r);
else if(l>mid) Update1(num*+,l,r);
else
{
Update1(num*,l,mid);
Update1(num*+,mid+,r);
}
segTree[num].sum=segTree[num*].sum+segTree[num*+].sum;
}
void Update2(int num,int l,int r)
{
if(segTree[num].flag == -) return ;
if(segTree[num].l == l && segTree[num].r ==r)
{
segTree[num].flag=-;
segTree[num].sum=;
return ;
}
int mid=(segTree[num].l +segTree[num].r)/;
if(segTree[num].flag==)
{
segTree[num*].sum=(segTree[num*].r -segTree[num*].l +);
segTree[num*+].sum=(segTree[num*+].r -segTree[num*+].l +);
segTree[num*].flag=;
segTree[num*+].flag=;
segTree[num].flag=;
}
if(r<=mid) Update2( num*,l,r);
else if(l>mid) Update2(num*+,l,r);
else
{
Update2(num*,l,mid);
Update2(num*+,mid+,r);
}
segTree[num].sum=segTree[num*].sum+segTree[num*+].sum;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int k;
int A,F,B;
scanf("%d%d",&n,&m);
Build(,,n);
while(m--)
{
scanf("%d",&k);
if(k==)
{
scanf("%d%d",&A,&F);
A++;
int tol=n-A+-query(,A,n);
if(tol==)
{
cout<<"Can not put any one."<<endl;
continue;
} if(tol<F) F=tol;
int l=A;
int r=n;
int mid;
int pos1=n+,pos2=n+;
while(l<=r)
{
mid=(l+r)/;
int tol=mid-A+-query(,A,mid);
if(tol>=) pos1=min(pos1,mid),r=mid-;
else l=mid+;
} l=pos1;
r=n;
while(l<=r)
{
mid=(l+r)/;
int tol=mid-pos1+-query(,pos1,mid);
if(tol>=F) pos2=min(pos2,mid),r=mid-;
else l=mid+;
}
cout<<pos1-<<" "<<pos2-<<endl;
Update1(,pos1,pos2);
}
else
{
scanf("%d%d",&A,&B);
A++;B++;
int tol=query(,A,B);
cout<<tol<<endl;
Update2(,A,B);
} }
cout<<endl;
}
return ;
}

hdu4614 Vases and Flowers 线段树+二分的更多相关文章

  1. hdu4614 Vases and Flowers 线段树

    Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...

  2. HDU-4614 Vases and Flowers 线段树区间更新

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 线段树保存区间是否被覆盖以及区间的和即可,在询问的时候在线段树上二分查找就可以了...代码写得比 ...

  3. HDU 4614 Vases and Flowers(线段树+二分)

    题目链接 比赛的时候一直想用树状数组,但是树状数组区间更新之后,功能有局限性.线段树中的lz标记很强大,这个题的题意也挺纠结的. k = 1时,从a开始,插b个花,输出第一个插的位置,最后一个的位置, ...

  4. hdu 4614 Vases and Flowers 线段树

    题目链接 一共n个盒子, 两种操作, 第一种是给出两个数x, y, 从第x个盒子开始放y朵花, 一个盒子只能放一朵, 如果某个盒子已经有了, 那么就跳过这个盒子放下面的盒子. 直到花放完了或者到了最后 ...

  5. hdu4614 线段树+二分 插花

    Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...

  6. Codeforces Gym 100803G Flipping Parentheses 线段树+二分

    Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...

  7. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  8. 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块

    !!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...

  9. luogu4422 [COCI2017-2018#1] Deda[线段树二分]

    讨论帖:线段树二分的题..我还考场切过..白学 这题我一年前的模拟赛考场还切过,现在就不会了..好菜啊. 显然直接线段树拆成$\log n$个区间,然后每个区间在进行线段树二分即可. UPD:复杂度分 ...

随机推荐

  1. (转)cacti无图无数据等常见问题排查

    推荐阅读:零基础学习Nagios http://www.51ou.com/browse/nagios/52001.htmlNagios安装配置教程 http://www.51ou.com/browse ...

  2. 疑问:Spring中构造器、init-method、@PostConstruct、afterPropertiesSet孰先孰后,自动注入发生时间

    问题:今天想写一个通用点的方法,根据传入的参数的类型(clazz对象),判断使用哪个mapper来插入mysql数据库. 下面是我的写法: public interface BizNeeqCommon ...

  3. 转:java实例化对象的过程

    学习JAVA这门面向对象的语言,实质就是不断地创建类,并把类实例化为对象并调用方法.对于初学JAVA的人总搞清楚对象是如何实例化的,假如类之间存在继承关系,那就更糊涂了.下面我们通过两个例题来说明对象 ...

  4. 让Xcode日志输出中文

    有的时候xcode打印后台返回的日志,明明后台返回的是中文,但是在xcode的日志里面却不是中文,而是unicode编码,这个就比较坑,因为看不到内容. 其实解决办法有两种: 第一种就是给xcode安 ...

  5. SUSE linux 使用LVM安装系统和管理

    引出 在我们安装好linux系统后会发现在需要修改磁盘分区的时候会比较困难,系统安装的/目录的文件系统要更改基本不太可能,其他目录如/home目录也比较困难.但是系统安装时要是采用的LVM管理的方式安 ...

  6. 山东省济南市历城第二中学——洛谷图论入门题--基本题必做 图的遍历—3.骑马修栅栏(fence)

    由于我这个破题提交了十四五遍,所以我决定写篇博客来记录一下. 这个题的题目描述是这样的 首先一看这个题我瞬间就想到了一笔画问题(欧拉回路). 对于能够一笔画的图,我们有以下两个定理. 定理1:存在欧拉 ...

  7. 【转】JSON和JSONP

      前言 由于Sencha Touch 2这种开发模式的特性,基本决定了它原生的数据交互行为几乎只能通过AJAX来实现. 当然了,通过调用强大的PhoneGap插件然后打包,你可以实现100%的Soc ...

  8. Access-自定义控件TabControl

    p{ font-size: 15px; } .alexrootdiv>div{ background: #eeeeee; border: 1px solid #aaa; width: 99%; ...

  9. 老李分享:接电话之uiautomator 1

    老李分享:接电话之uiautomator   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:9 ...

  10. 老李推荐: 第3章2节《MonkeyRunner源码剖析》脚本编写示例: MonkeyDevice API使用示例 4

    第七步:保存新增加日记 代码3-2-7 增加日记-保存日记 #Step7: Save the note by touch on the "save" menu entry by c ...