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

  Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A and try to put a flower in the vase. If the there is no flower in the vase, she will put a flower in it, otherwise she skip this vase. And then she will try put in the vase A+1, A+2, ..., N-1, until there is no flower left or she has tried the vase N-1. The left flowers will be discarded. Of course, sometimes she will clean the vases. Because there are too many vases, she randomly choose to clean the vases numbered from A to B(A <= B). The flowers in the cleaned vases will be discarded.

Input

  The first line contains an integer T, indicating the number of test cases.
  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

  For each operation of which K is 1, output the position of the vase in which Alice put the first flower and last one, separated by a blank. If she can not put any one, then output 'Can not put any one.'. For each operation of which K is 2, output the number of discarded flowers. 
  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(线段树区间更新+二分查找)的更多相关文章

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

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

  2. HDU-4614 Vases and Flowers 线段树区间更新

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 线段树保存区间是否被覆盖以及区间的和即可,在询问的时候在线段树上二分查找就可以了...代码写得比 ...

  3. hdu 4614 Vases and Flowers 线段树

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

  4. HDU.1556 Color the ball (线段树 区间更新 单点查询)

    HDU.1556 Color the ball (线段树 区间更新 单点查询) 题意分析 注意一下pushdown 和 pushup 模板类的题还真不能自己套啊,手写一遍才行 代码总览 #includ ...

  5. HDU 1556 Color the ball(线段树区间更新)

    Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...

  6. (简单) HDU 1698 Just a Hook , 线段树+区间更新。

    Description: In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of ...

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

  8. hdu - 1689 Just a Hook (线段树区间更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=1698 n个数初始每个数的价值为1,接下来有m个更新,每次x,y,z 把x,y区间的数的价值更新为z(1<= ...

  9. 2014多校第四场1006 || HDU 4902 Nice boat (线段树 区间更新)

    题目链接 题意 : 给你n个初值,然后进行两种操作,第一种操作是将(L,R)这一区间上所有的数变成x,第二种操作是将(L,R)这一区间上所有大于x的数a[i]变成gcd(x,a[i]).输出最后n个数 ...

随机推荐

  1. ETL优化

    ETL优化 Extract.Transform.Load,对异构数据源进行数据处理. 设立基线标准,根据硬盘.网络传输速度,多测测量得到数据量(m)/时间(s)的比值,找线性关系.建立基线作为调试和优 ...

  2. 谈谈我近一个半月的dp练习

    前请提示:https://www.cnblogs.com/caiyishuai/p/9047991.html   配合这篇文章食用风味更佳哦! 首先十分感谢henry_y提供的50道dp练习,链接在这 ...

  3. JS向固定数组中添加不重复元素并冒泡排序

    向数组{7,20,12,6,25}中添加一个不重复的数字,然后按照从小到大的顺序排列 源代码: <!DOCTYPE html> <html> <head> < ...

  4. Nacos快速开始

    Nacos是一个服务发现.配置管理和服务管理的组件. 说到服务注册与发现,我想到Eureka.Zookeeper 说到服务治理,我想到Dubbo 说到配置管理,我想到Apollo 作为后起之秀的Nac ...

  5. gulp 学习入门

    const gulp = require('gulp'); const less = require('gulp-less') // 定义任务 gulp.task('helloGulp',functi ...

  6. IO流处理文件读取到字节数组,再从字节数组读取到文件,Java实现

    package cn.zhang.io; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; impo ...

  7. 2020/1/27代码审计学习之SQL注入漏洞

    PHP代码审计SQL注入漏洞 0x00 首先明确什么是SQL注入,SQL语句必须掌握. 常见的注入总的来说可以分为两大类:数字型和字符型. 这两类中包含了诸如报错注入,宽字节注入,盲注,二次注入,co ...

  8. Maven--Cargo远程部署

    参考:https://www.digitalocean.com/community/questions/how-to-access-tomcat-8-admin-gui-from-different- ...

  9. 18 11 07 pygame 继续使用

    ---恢复内容开始--- 1  给原来的游戏不定时  增加一些敌机  用到了pygame的定时器    定时器就是每隔一段时间  就进行一次相同的操作 2 pyagame 在捕获键盘操作有两种 1  ...

  10. ZJNU 1372 - 破解情书

    取模运算在数组内循环解密,否则会MLE /* Written By StelaYuri */ #include<stdio.h> ],cn[]; int main() { int i,j, ...