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:复杂度分 ...
随机推荐
- iOS开发之UIApplication和delegate
1.概述 所有的移动操作系统都有个致命的缺点:app很容易受到打扰.比如一个来电或者锁屏会导致app进入后台甚至被终止. 还有很多其它类似的情况会导致app受到干扰,在app受到干扰时,会产生一些系统 ...
- benchmark 库
性能测试的库 https://github.com/bestiejs/benchmark.js
- Windows Mobile 常用键值VK对应表
#define VK_TSOFT2 VK_F2 // Softkey 2 #define VK_TTALK VK_F3 // Talk ...
- 串的模式匹配和KMP算法
在对字符串的操作中,我们经常要用到子串的查找功能,我们称子串为模式串,模式串在主串中的查找过程我们成为模式匹配,KMP算法就是一个高效的模式匹配算法.KMP算法是蛮力算法的一种改进,下面我们先来介绍蛮 ...
- underscore.js,js工具库
官方文档:http://underscorejs.org/ var totalCheckPriceVal = _.reduce(tableData[0],function(memo,num){ var ...
- .NET Core开源组件:后台任务利器之Hangfire
一.简述 Hangfire作为一款高人气且容易上手的分布式后台执行服务,支持多种数据库.在.net core的环境中,由Core自带的DI管理着生命周期,免去了在NF4.X环境中配置always ru ...
- Luogu2723丑数Humble Numbers【归并排序】
Luogu2723丑数Humble Numbers 题目背景 对于一给定的素数集合 S = {p1, p2, ..., pK},考虑一个正整数集合,该集合中任一元素的质因数全部属于S.这个正整数集合包 ...
- 微服务架构的简单实现-Stardust
微服务架构,一个当下比较火的概念了.以前也只是了解过这方面的概念,没有尝试过.想找找.NET生态下面是否有现成的实现,可是没找到,就花了大半个月的闲暇时间,遵循着易用和简单,实现了一个微服务框架,我叫 ...
- css3+js 实现砸金蛋效果
最近闲来无事,在网上看到有人写了个砸金蛋的效果,他是没有用到css3的,当时我就感觉没什么动态效果 感觉体验不是很好,所有我就想用css3来改下,于是也来试着写写. 本来想弄个视频给你们看看效果的,但 ...
- Swift: 使用cocoapods进行单元测试找不到bridge_header文件
准备对项目进行单元测试,在 command + U 运行时出现了错误找不到桥接文件,如下图所示. 找了各种资料,终于解决了,如下图,可以发现search path中路径都为空,由于unit test是 ...