hdu4614 Vases and Flowers 线段树+二分
题目链接: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 线段树+二分的更多相关文章
- hdu4614 Vases and Flowers 线段树
Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...
- HDU-4614 Vases and Flowers 线段树区间更新
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 线段树保存区间是否被覆盖以及区间的和即可,在询问的时候在线段树上二分查找就可以了...代码写得比 ...
- HDU 4614 Vases and Flowers(线段树+二分)
题目链接 比赛的时候一直想用树状数组,但是树状数组区间更新之后,功能有局限性.线段树中的lz标记很强大,这个题的题意也挺纠结的. k = 1时,从a开始,插b个花,输出第一个插的位置,最后一个的位置, ...
- hdu 4614 Vases and Flowers 线段树
题目链接 一共n个盒子, 两种操作, 第一种是给出两个数x, y, 从第x个盒子开始放y朵花, 一个盒子只能放一朵, 如果某个盒子已经有了, 那么就跳过这个盒子放下面的盒子. 直到花放完了或者到了最后 ...
- hdu4614 线段树+二分 插花
Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...
- Codeforces Gym 100803G Flipping Parentheses 线段树+二分
Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...
- Codeforces Gym 100231B Intervals 线段树+二分+贪心
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...
- 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块
!!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...
- luogu4422 [COCI2017-2018#1] Deda[线段树二分]
讨论帖:线段树二分的题..我还考场切过..白学 这题我一年前的模拟赛考场还切过,现在就不会了..好菜啊. 显然直接线段树拆成$\log n$个区间,然后每个区间在进行线段树二分即可. UPD:复杂度分 ...
随机推荐
- SQLServer中间接实现函数索引或者Hash索引
本文出处:http://www.cnblogs.com/wy123/p/6617700.html SQLServer中没有函数索引,在某些场景下查询的时候要根据字段的某一部分做查询或者经过某种计算之后 ...
- WEB开发性能优化--核心定义介绍篇(1)
推荐理由 随着 互联网的蓬勃发展,并且伴随着产品功能的越来越复杂,对于技术人员来说最大的挑战就是如何在保证业务快速发展的同时,也可保证不断复杂的业务对用户体验的影响,其中对用户来说最重要的体验指标是如 ...
- Nuget Server 搭建
每个女人都有很多包包:其实男人也有,但只有会写程序的男人才有 -- 代码世界中的大"包"小"包".这些大包小包,有花钱买的,有从开源市场淘的,也有自己或同事亲手 ...
- js获取url中的参数方法
直接调用函数即可,函数如下: function getURLParam(name) { return decodeURIComponent((new RegExp('[?|&]' + name ...
- 老李分享:天使投资 vs. 风险投资 vs. 私募股权融资
天使投资(Angel Capital) 创意阶段(idea stage)到种子阶段(seed stage) 0 – 1百万美元营业额 还没有盈利 小股东 风险异常的高 不存在负债情况 风险投资(Ven ...
- [编织消息框架][JAVA核心技术]动态代理应用4
基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...
- C语言常见错误笔记
1. 职业化的程序员起码要具备两点: 1)基本的软件技能 2)不犯低级的错误 2. 修改函数的形参是没用的,函数本身占用的存储单元在堆栈中分配,入口参数的值会在函数入口处拷贝到堆栈中,一旦函数返回,其 ...
- 5 安装Alloc服务
cnblogs-DOC 1.服务器环境 2.安装Redis3.安装Zookeeper4.安装MPush5.安装Alloc服务6.完整测试7.常见问题 一.Linux安装Mpush-Alloc [roo ...
- 初次接触 Android Studio FAQ
1. 2. 3. 4. 6. 7. Tools -> Adnroid -> enable ADB integration 8.官方模拟器太慢,还是自己下个第三方模拟器吧. http:/ ...
- python基本数据类型——int
一.int的范围 python2: 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1: 在64位系统上,整数的位数为64位,取值范围为-2**63-2**63-1: pyth ...