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个数 ...
随机推荐
- ETL优化
ETL优化 Extract.Transform.Load,对异构数据源进行数据处理. 设立基线标准,根据硬盘.网络传输速度,多测测量得到数据量(m)/时间(s)的比值,找线性关系.建立基线作为调试和优 ...
- 谈谈我近一个半月的dp练习
前请提示:https://www.cnblogs.com/caiyishuai/p/9047991.html 配合这篇文章食用风味更佳哦! 首先十分感谢henry_y提供的50道dp练习,链接在这 ...
- JS向固定数组中添加不重复元素并冒泡排序
向数组{7,20,12,6,25}中添加一个不重复的数字,然后按照从小到大的顺序排列 源代码: <!DOCTYPE html> <html> <head> < ...
- Nacos快速开始
Nacos是一个服务发现.配置管理和服务管理的组件. 说到服务注册与发现,我想到Eureka.Zookeeper 说到服务治理,我想到Dubbo 说到配置管理,我想到Apollo 作为后起之秀的Nac ...
- gulp 学习入门
const gulp = require('gulp'); const less = require('gulp-less') // 定义任务 gulp.task('helloGulp',functi ...
- IO流处理文件读取到字节数组,再从字节数组读取到文件,Java实现
package cn.zhang.io; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; impo ...
- 2020/1/27代码审计学习之SQL注入漏洞
PHP代码审计SQL注入漏洞 0x00 首先明确什么是SQL注入,SQL语句必须掌握. 常见的注入总的来说可以分为两大类:数字型和字符型. 这两类中包含了诸如报错注入,宽字节注入,盲注,二次注入,co ...
- Maven--Cargo远程部署
参考:https://www.digitalocean.com/community/questions/how-to-access-tomcat-8-admin-gui-from-different- ...
- 18 11 07 pygame 继续使用
---恢复内容开始--- 1 给原来的游戏不定时 增加一些敌机 用到了pygame的定时器 定时器就是每隔一段时间 就进行一次相同的操作 2 pyagame 在捕获键盘操作有两种 1 ...
- ZJNU 1372 - 破解情书
取模运算在数组内循环解密,否则会MLE /* Written By StelaYuri */ #include<stdio.h> ],cn[]; int main() { int i,j, ...