HDU 4614 Vases and Flowers(线段树+二分)
Vases and Flowers
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3220 Accepted Submission(s): 1273
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 one blank line after each test case.
题目链接:HDU 4614
题意就是给一个编号为0~N-1的花瓶,给一系列操作:1、从起始点S开始插入F朵花,插入时连续地从左到右扫描过去若花瓶有空且花没用完就一定要插到花瓶里,最后要么花用完了要么没位置可以放置了;2、清空编号从L到R花瓶。
这题第二问明显可以用线段树做,而且由于前缀和的缘故,花的前缀和数量在编号序列上具有单调性,因此第一问可以用二分做,但是二分开头简单,二分结尾就比较恶心,调试了很久,仔细考虑可以发现会有这样一个容易错误的地方:若从头到尾空位比花少,则终点为第一个达到最大空位的位置,而不是一直到结尾,因此要仅当当前位置的前缀空位和等于最大空位数的时候才记录终点T。如果二分结尾不正确估计第二组样例会对不上
代码:
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 50010;
struct seg
{
int l, mid, r;
int sum, add;
inline int len()
{
return r - l + 1;
}
};
seg T[N << 2]; inline void pushup(int k)
{
T[k].sum = T[LC(k)].sum + T[RC(k)].sum;
}
inline void pushdown(int k)
{
if (!T[k].add)
return ;
T[LC(k)].add = T[k].add;
T[RC(k)].add = T[k].add;
T[LC(k)].sum = (T[k].add == 1) * T[LC(k)].len();
T[RC(k)].sum = (T[k].add == 1) * T[RC(k)].len();
T[k].add = 0;
}
void build(int k, int l, int r)
{
T[k].l = l;
T[k].r = r;
T[k].mid = MID(l, r);
T[k].sum = T[k].add = 0;
if (l == r)
return ;
else
{
build(LC(k), l, T[k].mid);
build(RC(k), T[k].mid + 1, r);
}
}
void update(int k, int l, int r, int flag)
{
if (l <= T[k].l && T[k].r <= r)
{
T[k].add = flag;
T[k].sum = (flag == 1 ? T[k].len() : 0);
}
else
{
pushdown(k);
if (l <= T[k].mid)
update(LC(k), l, r, flag);
if (r > T[k].mid)
update(RC(k), l, r, flag);
pushup(k);
}
}
int query(int k, int l, int r)
{
if (l <= T[k].l && T[k].r <= r)
return T[k].sum;
else
{
pushdown(k);
if (r <= T[k].mid)
return query(LC(k), l, r);
else if (l > T[k].mid)
return query(RC(k), l, r);
else
return query(LC(k), l, T[k].mid) + query(RC(k), T[k].mid + 1, r);
}
}
int main(void)
{
int tcase, n, m, ops, l, r;
scanf("%d", &tcase);
while (tcase--)
{
scanf("%d%d", &n, &m);
build(1, 0, n - 1);
while (m--)
{
scanf("%d%d%d", &ops, &l, &r);
if (ops == 2)
{
int discard = query(1, l, r);
update(1, l, r, -1);
printf("%d\n", discard);
}
else if (ops == 1)
{
int S = -1; //二分找到第一个为空的点
int L = l, need = r, R = n - 1;
while (L <= R)
{
int mid = (L + R) >> 1;
if (query(1, l, mid) < mid - l + 1)
{
S = mid;
R = mid - 1;
}
else
L = mid + 1;
}
if (S == -1)//连开头位置都不存在,肯定位置全满了
puts("Can not put any one.");
else
{
int maxmvacnt = (n - 1 - S + 1) - query(1, S, n - 1);//用实际上最大的空位数而不是花朵数去二分
need = min<int>(need, maxmvacnt);
int T = -1;
int L = S, R = n - 1;
while (L <= R)
{
int mid = (L + R) >> 1;
int vacant = mid - S + 1 - query(1, S, mid);
if (vacant < need)
L = mid + 1;
else if (vacant == need) //此处与普通二分有一点不同
{
T = mid;
R = mid - 1;
}
else
R = mid - 1;
}
printf("%d %d\n", S, T);
update(1, S, T, 1);
}
}
}
putchar('\n');
}
return 0;
}
HDU 4614 Vases and Flowers(线段树+二分)的更多相关文章
- HDU 4614 Vases and Flowers(线段树+二分)
题目链接 比赛的时候一直想用树状数组,但是树状数组区间更新之后,功能有局限性.线段树中的lz标记很强大,这个题的题意也挺纠结的. k = 1时,从a开始,插b个花,输出第一个插的位置,最后一个的位置, ...
- hdu 4614 Vases and Flowers 线段树
题目链接 一共n个盒子, 两种操作, 第一种是给出两个数x, y, 从第x个盒子开始放y朵花, 一个盒子只能放一朵, 如果某个盒子已经有了, 那么就跳过这个盒子放下面的盒子. 直到花放完了或者到了最后 ...
- hdu4614 Vases and Flowers 线段树+二分
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意: 给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花. ...
- HDU 4614 Vases and Flowers(二分+线段树区间查询修改)
描述Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to ...
- HDU 4614 Vases and Flowers 【线段树】+【二分】
<题目链接> 题目大意: 有n个花瓶,每个花瓶中只能放一朵花.两种操作,一种是从A开始放F朵花,如果有的花瓶中已经有花则跳过这个花瓶,往下一个花瓶放:第二种是将区间[A,B]之间花瓶中的花 ...
- HDU 4614 Vases and Flowers (2013多校2 1004 线段树)
Vases and Flowers Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others ...
- HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题目大意:有n个空花瓶,有两种操作: 操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B ...
- HDU 4614 Vases and Flowers (2013多校第二场线段树)
题意摘自:http://blog.csdn.net/kdqzzxxcc/article/details/9474169 ORZZ 题意:给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每 ...
- hdu 4614 Vases and Flowers(线段树:成段更新)
线段树裸题.自己写复杂了,准确说是没想清楚就敲了. 先是建点为已插花之和,其实和未插花是一个道理,可是开始是小绕,后来滚雪球了,跪了. 重新建图,分解询问1为:找出真正插画的开始点和终止点,做成段更新 ...
随机推荐
- SpringBoot操作MongoDB实现增删改查
本篇博客主讲如何使用SpringBoot操作MongoDB. SpringBoot操作MongoDB实现增删改查 (1)pom.xml引入依赖 <dependency> <group ...
- Bootstrap历练实例:警告框(Alert)插件事件
事件 下表列出了警告框(Alert)插件中要用到的事件.这些事件可在函数中当钩子使用. 事件 描述 实例 close.bs.alert 当调用 close 实例方法时立即触发该事件. $('#myal ...
- ZRDay6A. 萌新拆塔(三进制状压dp)
题意 Sol 这好像是我第一次接触三进制状压 首先,每次打完怪之后吃宝石不一定是最优的,因为有模仿怪的存在,可能你吃完宝石和他打就GG了.. 因此我们需要维护的状态有三个 0:没打 1:打了怪物 没吃 ...
- 16.1-Jenkins持续集成01—Jenkins服务搭建和部署
分类: Linux架构篇 一.介绍Jenkins 1.Jenkins概念 Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台.这是一个免费的源代码,可以处理任何 ...
- 在windows上搭建镜像yum站的方法
在windows上搭建镜像yum站的方法(附bat脚本) 分类: 运维基本功,其他 方法一:支持rsync的网站 对于常用的centos.Ubuntu.等使用官方yum源在 http://mi ...
- libevent 信号事件实现方式
学会使用libevent,才能真正的掌握其是实现原理,我们先从一个简短的测试用例开始: #include <sys/types.h> #include <sys/stat.h> ...
- java中equals和==区别
equals 方法是 java.lang.Object 类的方法. 有两种用法说明: (1)对于字符串变量来说,使用“==”和“equals()”方法比较字符串时,其比较方法不同. “==”比较两个变 ...
- Python 信号处理 signal 模块
Table of Contents 1. signal模块简介 1.1. signal简单示例 1.2. signal说明 1.2.1. 基本的信号名 1.2.2. 常用信号处理函数 2. signa ...
- python基础——18(面向对象2+异常处理)
一.组合 自定义类的对象作为另一个类的属性. class Teacher: def __init__(self,name,age): self.name = name self.age = age t ...
- python项目中输出指定颜色的日志
起因 在开发项目过程中,为了方便调试代码,经常会向stdout中输出一些日志,默认的这些日志就直接显示在了终端中.而一般的应用服务器,第三方库,甚至服务器的一些通告也会在终端中显示,这样就搅乱了我们想 ...