HDU-4614 Vases and Flowers(线段树区间更新+二分查找)
http://acm.hdu.edu.cn/showproblem.php?pid=4614
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Problem Description
Input
For each test case, the first line contains two integers N(1 < N < 50001) and M(1 < M < 50001). N is the number of vases, and M is the operations of Alice. Each of the next M lines contains three integers. The first integer of one line is K(1 or 2). If K is 1, then two integers A and F follow. It means Alice receive F flowers and try to put a flower in the vase A first. If K is 2, then two integers A and B follow. It means the owner would like to clean the vases numbered from A to B(A <= B).
Output
Output one blank line after each test case.
Sample Input
Sample Output
Can not put any one. 3
题目大意:
有n个花瓶,标号0 ~ n−1。有m个操作,
‘1 A F′,表示从A位置开始插F朵花,遇到有花的花瓶跳过。到最后一个花瓶都还有花剩余,丢弃剩下的花。
‘2 A B′,表示将区间[A,B]内的花瓶全部清空。(A≤B)
对于每个1操作,输出第一个和最后一个插花的位置,如果一朵花都插不了,输出‘Can not put any one.’;对于每个2操作,输出区间[A,B]内被清空的花瓶的数量。
解题思路:
直接线段树存区间内的空花瓶数量。原来标号0 ~ n−1,但我线段树序号习惯了1 ~ n。
设num(l,r)为区间[l,r]的空花瓶数。
对于一个1操作,首先判一下num(A,n)是否大于0。
因为区间[A,n]的空花瓶数是单调不递减的,所以可以通过二分查找到 一个最小的位置L,使得num(A,L)=1,则此时的L就是第一个插花的位置。
同样二分找到一个最小的位置R,使得num(A,R)=min(F,num(A,n)),则此时的R就是最后一个插花的位置。(输出时记得减1)
对于一个2操作,直接询问区间[A,B]的空花瓶数,拿总数一减,输出,然后更新区间即可。
代码如下:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <map>
#include <math.h>
const int INF=0x3f3f3f3f;
typedef long long LL;
const int mod=1e9+;
const int maxn=1e5+;
using namespace std; struct SegTree_node
{
int l;
int r;
int num;//区间内空瓶的数量
int tag;//如果为-1则为初始状态,不用向下更新,如果为0意思将子区间内的花清空,为1为插满花
}SegTree[<<]; int n,m; void PushUp(int rt)//向上传递区间信息
{
SegTree[rt].num=SegTree[rt<<].num+SegTree[rt<<|].num;
} void PushDown(int rt)//向下传递状态
{
if(SegTree[rt].tag!=-)
{
SegTree[rt<<].tag=SegTree[rt<<|].tag=SegTree[rt].tag;
int mid=(SegTree[rt].l+SegTree[rt].r)>>;
SegTree[rt<<].num=(mid-SegTree[rt].l+)*SegTree[rt].tag;
SegTree[rt<<|].num=(SegTree[rt].r-mid)*SegTree[rt].tag;
SegTree[rt].tag=-;
}
} void Build(int l,int r,int rt)
{
SegTree[rt].l=l;
SegTree[rt].r=r;
SegTree[rt].num=r-l+;
SegTree[rt].tag=-;
if(l==r)
return ;
int mid=(l+r)>>;
Build(l,mid,rt<<);
Build(mid+,r,rt<<|);
} void Update(int L,int R,int f,int rt)
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(L<=l&&R>=r)
{
SegTree[rt].num=(r-l+)*f;//先计算
SegTree[rt].tag=f;//标记当前区间
return ;
}
if(l==r)//不要忘记
return ;
PushDown(rt);//向下传递状态
int mid=(l+r)>>;
if(L<=mid)
Update(L,R,f,rt<<);
if(R>mid)
Update(L,R,f,rt<<|);
PushUp(rt);
} int Query(int L,int R,int rt)//得到区间[L,R]中的空花瓶数
{
int l=SegTree[rt].l;
int r=SegTree[rt].r;
if(R<l||L>r)
return ;
if(L<=l&&R>=r)
return SegTree[rt].num;
PushDown(rt);
int mid=(l+r)>>;
int sum=;
if(L<=mid)
sum+=Query(L,R,rt<<);
if(R>mid)
sum+=Query(L,R,rt<<|);
return sum;
} int dive(int x,int num)//二分查找,第一个为开始的位置,第二个参数为要插花的个数
{
int l=x;
int r=n;
int ans=;
while(l<=r)
{
int mid=(l+r)>>;
if(Query(x,mid,)>=num)
{
ans=mid;
r=mid-;
}
else
l=mid+;
}
return ans;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
Build(,n,);
for(int i=;i<=m;i++)
{
int op;
scanf("%d",&op);
if(op==)
{
int A,F;
scanf("%d %d",&A,&F);
A++;//存储时序号从一开始,故序号要全加一,下同
int cnt=Query(A,n,);//得到区间[A, n]中的空花瓶数
if(cnt==)
printf("Can not put any one.\n");
else
{
int L=dive(A,);//二分左端点(第1个能插花的位置)
int R=dive(A,min(cnt,F));//二分右端点(最后一个能插花的位置)
Update(L,R,,);//将区间[L,R]的花瓶全部插满
printf("%d %d\n",L-,R-);
}
}
else if(op==)
{
int A,B;
scanf("%d %d",&A,&B);
A++;
B++;
printf("%d\n",B-A+-Query(A,B,));
Update(A,B,,);//将区间[A,B]的花瓶全部清空
}
}
printf("\n");
}
return ;
}
下面是kuangbin大佬用另一种模型的线段树写的,虽然有点麻烦,但是有空还是值得一看:https://www.cnblogs.com/kuangbin/p/3214805.html
HDU-4614 Vases and Flowers(线段树区间更新+二分查找)的更多相关文章
- HDU 4614 Vases and Flowers(线段树+二分)
题目链接 比赛的时候一直想用树状数组,但是树状数组区间更新之后,功能有局限性.线段树中的lz标记很强大,这个题的题意也挺纠结的. k = 1时,从a开始,插b个花,输出第一个插的位置,最后一个的位置, ...
- HDU-4614 Vases and Flowers 线段树区间更新
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 线段树保存区间是否被覆盖以及区间的和即可,在询问的时候在线段树上二分查找就可以了...代码写得比 ...
- hdu 4614 Vases and Flowers 线段树
题目链接 一共n个盒子, 两种操作, 第一种是给出两个数x, y, 从第x个盒子开始放y朵花, 一个盒子只能放一朵, 如果某个盒子已经有了, 那么就跳过这个盒子放下面的盒子. 直到花放完了或者到了最后 ...
- HDU.1556 Color the ball (线段树 区间更新 单点查询)
HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...
- HDU 1556 Color the ball(线段树区间更新)
Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...
- (简单) HDU 1698 Just a Hook , 线段树+区间更新。
Description: In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of ...
- HDU 1698 Just a Hook(线段树区间更新查询)
描述 In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes ...
- hdu - 1689 Just a Hook (线段树区间更新)
http://acm.hdu.edu.cn/showproblem.php?pid=1698 n个数初始每个数的价值为1,接下来有m个更新,每次x,y,z 把x,y区间的数的价值更新为z(1<= ...
- 2014多校第四场1006 || HDU 4902 Nice boat (线段树 区间更新)
题目链接 题意 : 给你n个初值,然后进行两种操作,第一种操作是将(L,R)这一区间上所有的数变成x,第二种操作是将(L,R)这一区间上所有大于x的数a[i]变成gcd(x,a[i]).输出最后n个数 ...
随机推荐
- linux常用命令之------文件操作、文件查看、权限、打包压缩
1.一般公司把linux作为自己的应用服务器,将应用和服务器部署在上面 2.测试一般用来打包.压缩.查日志,写一个简单的shell 获得linux服务器的方式 a:网上租一台云服务器 b:安装vmwa ...
- redis(三)----连接池配置
1. 目录结构: 2. 测试源码 package com.redis; import redis.clients.jedis.Jedis; import redis.clients.jedis.Jed ...
- python里的文件I/O
Python 文件I/O 本章只讲述所有基本的的I/O函数,更多函数请参考Python标准文档. 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个用逗号隔开的表达式.此函数把你 ...
- 【JavaScript】回流(reflow)与重绘(repaint)
重绘与回流 首先要了解页面是如何呈现的: HTML文档加载后生成DOM树(包括display:none;元素): 在DOM树的基础上配合css样式结构体生成render树(不包含display:non ...
- DRF框架之序列化器初体验
首先,我们需要明白序列化和反序列化的过程指的是什么. 序列化操作:将模型数据 ---> 字典数据 --->JSON数据(响应JSON数据的操作) 反序列化操作:将JSON数据 ---> ...
- ArrayList扩容原理分析
1:代码解读和分析 1.1:构造方法分析 1: public ArrayList(int initialCapacity) { ) { this.elementData = new Object[in ...
- P(Y=y|x;θ)表示什么意思
https://blog.csdn.net/jh1137921986/article/details/88999539 在机器学习中,特别是学习到关于概率/似然估计方面的内容,经常看到类似P(Y=y| ...
- 吴裕雄--天生自然 JAVASCRIPT开发学习:HTML DOM 节点列表
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Git 报错:fatal: refusing to merge unrelated histories
背景:[接上篇git push 出错的随笔]当 pull 远端仓库到本地的时候,出现以下错误: 错误情况: 出错原因:主要原因还是在于本地仓库和远程仓库实际上是独立的两个仓库,假如我之前是直接以 cl ...
- UITableViewCell 的selectedBackgroundView
UITableViewCell中的selectedBackgroundView就是用于当用户点击cell的时候,选择状态的view,你可以对这个view进行颜色或者其他样式等做一些定制,可以达到点击之 ...