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

题意:

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

然后有2个操作。

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

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

操作看起来挺简单的但写起来还是有点复杂的

首先建树的时候可以设置变量first与ends分别表示一个区间最先出现的0和最后出现的0,sum=0

表示没放东西,sum=1表示放了。我们可以用二分来查找插完b朵花后的结尾区间。然后在寻找这个

区间的first与ends值之后就简单了。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int M = 5e4 + 10;
struct TnT {
int l , r , num , add , first , ends;
}T[M << 2];
int n , m;
void build(int l , int r , int p) {
int mid = (l + r) >> 1;
T[p].l = l , T[p].r = r , T[p].add = T[p].num = 0 , T[p].first = l , T[p].ends = r;
if(l == r) {
return ;
}
build(l , mid , p << 1);
build(mid + 1 , r , (p << 1) | 1);
}
void pushup(int p) {
T[p].num = T[p << 1].num + T[(p << 1) | 1].num;
if(T[p << 1].first == -1) {
T[p].first = T[(p << 1) | 1].first;
}
else if(T[(p << 1) | 1].first == -1) {
T[p].first = T[p << 1].first;
}
else {
T[p].first = min(T[(p << 1) | 1].first , T[p << 1].first);
}
if(T[(p << 1) | 1].ends == -1) {
T[p].ends = T[(p << 1) | 1].ends;
}
else if(T[(p << 1) | 1].ends == -1) {
T[p].ends = T[p << 1].ends;
}
else {
T[p].ends = max(T[(p << 1) | 1].ends , T[p << 1].ends);
}
}
void pushdown(int p) {
if(T[p].add == 1) {
T[p << 1].num = T[p << 1].r - T[p << 1].l + 1;
T[p << 1].first = -1;
T[p << 1].ends = -1;
T[(p << 1) | 1].num = T[(p << 1) | 1].r - T[(p << 1) | 1].l + 1;
T[(p << 1) | 1].first = -1;
T[(p << 1) | 1].ends = -1;
T[p << 1].add = T[p].add;
T[(p << 1) | 1].add = T[p].add;
}
if(T[p].add == -1) {
T[p << 1].first = T[p << 1].l;
T[p << 1].ends = T[p << 1].r;
T[p << 1].num = 0;
T[(p << 1) | 1].num = 0;
T[p << 1].add = T[p].add;
T[(p << 1) | 1].first = T[(p << 1) | 1].l;
T[(p << 1) | 1].ends = T[(p << 1) | 1].r;
T[(p << 1) | 1].add = T[p].add;
}
T[p].add = 0;
}
int query(int l , int r , int p) {
int mid = (T[p].l + T[p].r) >> 1;
if(T[p].l == l && T[p].r == r) {
return T[p].num;
}
pushdown(p);
if(mid >= r) {
return query(l , r , p << 1);
}
else if(mid < l) {
return query(l , r , (p << 1) | 1);
}
else {
return query(l , mid , p << 1) + query(mid + 1 , r , (p << 1) | 1);
}
}
int queryfr(int l , int r , int p) {
int mid = (T[p].l + T[p].r) >> 1;
if(T[p].l == l && T[p].r == r) {
return T[p].first;
}
pushdown(p);
if(mid >= r) {
return queryfr(l , r , p << 1);
}
else if(mid < l) {
return queryfr(l , r , (p << 1) | 1);
}
else {
int ans = queryfr(l , mid , p << 1);
if(ans == -1) {
return queryfr(mid + 1 , r , (p << 1) | 1);
}
else {
return ans;
}
}
}
int queryed(int l , int r , int p) {
int mid = (T[p].l + T[p].l) >> 1;
if(T[p].l == l && T[p].r == r) {
return T[p].ends;
}
pushdown(p);
if(mid >= r) {
return queryed(l , r , p << 1);
}
else if(mid < l) {
return queryed(l , r , (p << 1) | 1);
}
else {
int ans = queryed(mid + 1 , r , (p << 1) | 1);
if(ans == -1) {
return queryed(l , mid , p << 1);
}
else {
return ans;
}
}
}
void updata(int l , int r , int p , int ad) {
int mid = (T[p].l + T[p].r) >> 1;
if(T[p].l == l && T[p].r == r) {
if(ad == 1) {
T[p].add = 1;
T[p].num = T[p].r - T[p].l + 1;
T[p].first = -1;
T[p].ends = -1;
return ;
}
if(ad == -1) {
T[p].add = -1;
T[p].num = 0;
T[p].first = T[p].l;
T[p].ends = T[p].r;
return ;
}
}
pushdown(p);
if(mid >= r) {
updata(l , r , p << 1 , ad);
}
else if(mid < l) {
updata(l , r , (p << 1) | 1 , ad);
}
else {
updata(l , mid , p << 1 , ad);
updata(mid + 1 , r , (p << 1) | 1 , ad);
}
pushup(p);
}
int bisearch(int sta , int sum) {
int l = sta , r = n;
int ans = n;
while(l <= r) {
int mid = (l + r) >> 1;
int gg = query(sta , mid , 1);
gg = mid - sta + 1 - gg;
if(gg >= sum) {
r = mid - 1;
ans = mid;
}
else {
l = mid + 1;
}
}
return ans;
}
int main() {
int t;
scanf("%d" , &t);
while(t--) {
scanf("%d%d" , &n , &m);
build(1 , n , 1);
for(int i = 1 ; i <= m ; i++) {
int k , a , f;
scanf("%d%d%d" , &k , &a , &f);
if(k == 1) {
a++;
int res = query(a , n , 1);
res = n - a + 1 - res;
if(res == 0) {
printf("Can not put any one.\n");
continue;
}
int sum = min(res , f);
int ed = bisearch(a , sum);
int fr = queryfr(a , ed , 1);
updata(fr , ed , 1 , 1);
printf("%d %d\n" , fr - 1 , ed - 1);
}
if(k == 2) {
a++ , f++;
int res = query(a , f , 1);
updata(a , f , 1 , -1);
printf("%d\n" , res);
}
}
printf("\n");
}
return 0;
}

hdu 4614 Vases and Flowers(线段树)的更多相关文章

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

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

  2. hdu 4614 Vases and Flowers 线段树

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

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

    Vases and Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others ...

  4. 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 ...

  5. HDU 4614 Vases and Flowers(二分+线段树区间查询修改)

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

  6. HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题目大意:有n个空花瓶,有两种操作: 操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B ...

  7. hdu 4614 Vases and Flowers(线段树:成段更新)

    线段树裸题.自己写复杂了,准确说是没想清楚就敲了. 先是建点为已插花之和,其实和未插花是一个道理,可是开始是小绕,后来滚雪球了,跪了. 重新建图,分解询问1为:找出真正插画的开始点和终止点,做成段更新 ...

  8. HDU 4614 Vases and Flowers (2013多校第二场线段树)

    题意摘自:http://blog.csdn.net/kdqzzxxcc/article/details/9474169 ORZZ 题意:给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每 ...

  9. HDU 4614 Vases and Flowers 【线段树】+【二分】

    <题目链接> 题目大意: 有n个花瓶,每个花瓶中只能放一朵花.两种操作,一种是从A开始放F朵花,如果有的花瓶中已经有花则跳过这个花瓶,往下一个花瓶放:第二种是将区间[A,B]之间花瓶中的花 ...

  10. hdu 4614 Vases and Flowers

    http://acm.hdu.edu.cn/showproblem.php?pid=4614 直接线段树维护 代码: #include<iostream> #include<cstd ...

随机推荐

  1. Cell Phone Networ (树形dp-最小支配集)

    目录 Cell Phone Networ (树形dp-最小支配集) 题意 思路 题解 Cell Phone Networ (树形dp-最小支配集) Farmer John has decided to ...

  2. python3 编译安装

    前言: Linux下大部分系统默认自带python2.x的版本,最常见的是python2.6或python2.7版本,默认的python被系统很多程序所依赖,比如centos下的yum就是python ...

  3. Hyper-v设置linux固定ip

    一.创建CentOS 7专用的虚拟交换机 打开Hyper-v控制面板,找到右边的“虚拟交换机管理器” 进去后,点击“新建虚拟网络交换机”,填写名称后,选择“内部” 打开网络中心,修改配置如下图,注意i ...

  4. 数据结构之二叉树的构建C++版

    二叉树的构建要注意与链式表的区别,二叉树这里的构建十分低级,每个树只是构建了一个单一的二叉树节点,总体来看是有下向上构建的.用户需要手动去构建自己需要的树,而不是直接去插入数据就到二叉树中了,因为不是 ...

  5. 递归&分治&贪心

    递归 Recursion:通过函数体来进行的循环. 思路简单但效率低(建立函数的副本,消耗大量时间和内存).能用迭代就不用递归.递推公式+递推终止条件. 计算n阶乘,递归实现 def Factoria ...

  6. 初识JavaScript和面向对象

    1.javascript基本数据类型: number: 数值类型 string: 字符串类型 boolean: 布尔类型 null: 空类型 undefault:未定义类型 object: 基本数据类 ...

  7. node一键发布,并运行

    作为一个前端开发人员如果你只会写一些业务代码,从程序员的角度来考虑已经可以了.但是从架构的角度来考虑那远远不够: 在此记录下成长中的经历: 想要达成的目的:运行一个脚本实现代码的打包,上传至服务器并部 ...

  8. 认识Redies

    既然是作为了解性文章,那必然不会做很深入的解读.深入的解读以后会加上. 我们先来回答两个问题.通过这两个问题来开始我们的Redies入门之旅. Redies是什么? Redies有什么作用? Redi ...

  9. 基于jmeter+perfmon的稳定性测试记录

    1. 引子 最近承接了项目中一些性能测试的任务,因此决定记录一下,将测试的过程和一些心得收录下来. 说起来性能测试算是软件测试行业内,有些特殊的部分.这部分的测试活动,与传统的测试任务差别是比较大的, ...

  10. sql server数据库查询链接服务器

    服务器对象->链接服务器: 或者 select  * from sys.servers: 找到服务器对象名称 select  * from [服务器对象名称].[数据库名称].dbo.[表名]: