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. 《Thinking in Java》位运算

    按位操作符: 首先先记住一件事,方便理解:是否对应正负对应10. 1.与(&):11得1,10得0,00得0. 2.或(|):11得1,10得1,00得0. 3.异或(^):11得0,10得1 ...

  2. python刷LeetCode:27. 移除元素

    难度等级:简单 题目描述: 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O ...

  3. VUE中的MVVM模式

    1.传统MVP模式:业务逻辑相关的控制层 M:模型层,ajax请求 V:dom层,视图 P:控制器.js代码之类的 2.MVVM MVVM模式主要操作数据层,代码减少量是MVP的30%甚至70%

  4. MFC 打开Jpg文件

    UpdateWindow(); int height, width; CRect rect;//定义矩形类 CRect rect1; CImage image; //创建图片类 image.Load( ...

  5. 小白需要了解的Ajax和websocket的区别以及使用场景!

    在我们日常使用的互联网产品中,很多都是前后端数据的交互来完成的,说到数据交互就不得不提Ajax和websocket,它们可是数据交互的利器,那么它们分别是什么?websocket与Ajax轮询的区别又 ...

  6. 干货|CVE-2019-11043: PHP-FPM在Nginx特定配置下任意代码执行漏洞分析

    近期,国外安全研究员Andrew Danau,在参加夺旗赛(CTF: Capture the Flag)期间,偶然发现php-fpm组件处理特定请求时存在缺陷:在特定Nginx配置下,特定构造的请求会 ...

  7. centos7.4 测试CPU压力--命令搞定

    直接输入命令CPU消耗增加: cat /dev/urandom | gzip - > /dev/null 停止: 直接Ctrl+c结束

  8. Redhat7 开机启动服务

    #!/bin/sh ### BEGIN INIT INFO # Provides: jboss # Required-Start: $local_fs $remote_fs $network $sys ...

  9. qt使用了qstackedwidget里面放置了widget后对该子widget设置的样式无效

    关键字:子窗口样式无效 QStackedwidget 问题: 我有一个对话框,里面放了一个qstackedwidget,qstackedwidget放了N个子窗口,使用addwidget添加上去了: ...

  10. JAVE官方文档

    官网地址:http://www.sauronsoftware.it/projects/jave/manual.php JAVE manual Installation and requirements ...