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. Flink:动态表上的连续查询

    用SQL分析数据流 越来越多的公司在采用流处理技术,并将现有的批处理应用程序迁移到流处理或者为新的应用设计流处理方案.其中许多应用程序专注于分析流数据.分析的数据流来源广泛,如数据库交易,点击,传感器 ...

  2. python类(4)——自己造第一个轮子

    先做简单版本,再一步步增加功能 1.简单目的:要实现这样一个功能,能够连接服务器,登录账号,查询账号委托信息,如果有委托信息,撤销委托. 属性(不同账户之间差别):账户,密码 方法(不同账户之间都要用 ...

  3. [C/C++]编程规范一:头文件篇

    一般来说,每一个.cc或者.cpp文件对应一个头文件(.h文件),当然,也有例外,例如一些测试单元或者main文件,头文件的一些规范可以令代码可读性.程序的性能等大为改观,所以还是要注意头文件的规范问 ...

  4. tomcat8.5的安装、卸载、配置和部署

    安装和卸载 下载 http://tomcat.apache.org/ 环境变量 1.点击此电脑 右键—>属性. 2.创建变量名为CATALINA_HOME,的值为所解压安装tomcat的本地目录 ...

  5. Property or method "cancleInput" is not defined on the instance but referenced during render.

    因为我的点击事件,是动态添加上去的 报错如标题  [Vue warn]: Property or method "cancleInput" is not defined on th ...

  6. C#——发送邮件

    需要2个引用 using System.Net;using System.Net.Mail; using (MailMessage mailMessige=new MailMessage()) usi ...

  7. 题解【[FJOI2018]所罗门王的宝藏】

    本题解同步于luogu emmm切了近年省选题来写题解啦qwq 该题较其他省选题较水吧(否则我再怎么做的出来 思路是图论做法,做法上楼上大佬已经讲的很清楚了,我来谈谈代码实现上的一些细节 \[\tex ...

  8. 对Java面向对象中多态的理解

    理解的要点:多态意味着父亲的变量可以指向子类对象 面向对象程序设计的三大支柱是封装.继承和多态 封装对外把相应的属性和方法实现的细节进行了隐藏.继承关系使一个子类继承父亲的特征,并且加上了一些新的特征 ...

  9. Docker部署freeswitch

    1. clone配置文件到本地服务器 git clone https://github.com/BetterVoice/freeswitch-container.git 相关Dockerfile如下: ...

  10. GTX 1080显卡出错

    NVRM: RmInitAdapter failed! (0x26:0xffff:1097) NVRM: rm_init_adapter failed for device bearing minor ...