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

题目大意:有n个空花瓶,有两种操作:

     操作①:给出两个数字A,B,表示从第A个花瓶开始插花,插B朵花,输出第一个和最后一个插入的花瓶,如果任意花瓶都已经满了不能插花,则输出“Can not put any one.”。

     操作②:给出两个数字A,B,表示清空第A~B个花瓶,并输出清空掉的花朵数目。

解题思路:线段树,关于操作②,很简单弄个sum表示区间空花瓶数,计算时清空掉的花朵数=区间长度-sum。

     关于操作①,有两种解法,第一种就是记录更新每个区间的空花瓶的始末点,这样在插花时可以由此直接获得起点终点。

           第二种,就是乱搞,查找全空区间(都是空花瓶)然后插花,全空区间起点终点的获得就不用说了吧。复杂度真的是玄学(感觉完全算不出来),还以为会超时的,竟然比解法一还快点。。。

解法一:

 #include<stdio.h>
#include<algorithm>
#define LC(a) ((a<<1))
#define RC(a) ((a<<1)+1)
#define MID(a,b) ((a+b)>>1)
using namespace std;
typedef long long ll;
const int N = 5e4 + ; struct node {
ll l, r;
ll sum, Start, End, color;//Start是第一个空花瓶位置,End是最后一个空花瓶位置,color=-1,0,1代表初始化,清空,插花
}tree[N<<]; ll leave, Start, sum, End;
void pushup(ll p) {
//维护区间空花瓶数量
tree[p].sum = tree[LC(p)].sum + tree[RC(p)].sum;
tree[p].color = (tree[LC(p)].color == tree[RC(p)].color ? tree[LC(p)].color : -);
//维护空花瓶起点和终点
if (tree[LC(p)].Start != )
tree[p].Start = tree[LC(p)].Start;
else if (tree[LC(p)].End != )
tree[p].Start = tree[LC(p)].End;
else if (tree[RC(p)].Start != )
tree[p].Start = tree[RC(p)].Start;
else if (tree[RC(p)].End != )
tree[p].Start = tree[RC(p)].End;
else
tree[p].Start = ;
tree[p].End = max(max(tree[LC(p)].Start, tree[LC(p)].End), max(tree[RC(p)].Start, tree[RC(p)].End));
} void pushdown(ll p) {
if (tree[p].color == ) {
tree[LC(p)].sum = tree[LC(p)].r - tree[LC(p)].l + ;
tree[LC(p)].Start = tree[LC(p)].l;
tree[LC(p)].End = tree[LC(p)].r;
tree[RC(p)].sum = tree[RC(p)].r - tree[RC(p)].l + ;
tree[RC(p)].Start = tree[RC(p)].l;
tree[RC(p)].End = tree[RC(p)].r;
tree[LC(p)].color = tree[RC(p)].color = ;
}
else if (tree[p].color == ) {
tree[LC(p)].sum = tree[LC(p)].Start = tree[LC(p)].End = tree[RC(p)].sum = tree[RC(p)].Start = tree[RC(p)].End = ;
tree[LC(p)].color = tree[RC(p)].color = ;
}
} void build(ll p, ll l, ll r) {
tree[p].l = l;
tree[p].r = r;
tree[p].Start = tree[p].End = ;
tree[p].sum = ;
if (l == r) {
tree[p].Start = tree[p].End = l;
tree[p].sum = ;
tree[p].color = -;
return;
}
build(LC(p), l, MID(l, r));
build(RC(p), MID(l, r) + , r);
pushup(p);
}
//清空
void update(ll p, ll l, ll r) {
if (r<tree[p].l || l>tree[p].r)
return;
if (l <= tree[p].l&&r >= tree[p].r) {
sum += (tree[p].r - tree[p].l + - tree[p].sum);
tree[p].Start = tree[p].l;
tree[p].End = tree[p].r;
tree[p].sum = tree[p].r - tree[p].l + ;
tree[p].color = ;
return;
}
pushdown(p);
update(LC(p), l, r);
update(RC(p), l, r);
pushup(p);
}
//插花
void query(ll p, ll l, ll r) {
if (r<tree[p].l || l>tree[p].r)
return;
if (leave == || tree[p].sum == )
return;
if (l <= tree[p].l&&r >= tree[p].r) {
if (Start == )
Start = tree[p].Start;
if (leave >= tree[p].sum) {
leave -= tree[p].sum;
End = max(End, tree[p].End);
tree[p].sum = tree[p].Start = tree[p].End = ;
tree[p].color = ;
return;
}
}
pushdown(p);
query(LC(p), l, r);
query(RC(p), l, r);
pushup(p);
}
int main() {
ll q;
scanf("%I64d",&q);
while (q--) {
ll n, m;
scanf("%I64d %I64d",&n,&m);
build(, , n);
while (m--) {
ll k;
scanf("%I64d",&k);
//插花
if (k == ) {
ll a, f;
scanf("%I64d %I64d",&a,&f);
End = Start = ;
leave = f;
query(, a + , n);
if (Start == )
printf("Can not put any one.\n");
else
printf("%I64d %I64d\n",Start-,End-);
}
//清空
else {
ll a, b;
scanf("%I64d %I64d",&a,&b);
sum = ;
update(, a + , b + );
printf("%I64d\n",sum);
}
}
printf("\n");
}
return ;
}

解法二:

 #include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<string>
#define LC(a) (a<<1)
#define RC(a) (a<<1|1)
#define MID(a,b) ((a+b)>>1)
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=5e4+; int ans,x,Start,End,flag; struct node{
int sum,l,r;//sum表示空花瓶数
}tree[*N]; void pushdown(int p){
//全满
if(tree[p].sum==tree[p].r-tree[p].l+){
tree[LC(p)].sum=tree[LC(p)].r-tree[LC(p)].l+;
tree[RC(p)].sum=tree[RC(p)].r-tree[RC(p)].l+;
}
//全空
else if(tree[p].sum==)
tree[LC(p)].sum=tree[RC(p)].sum=;
} void pushup(int p){
tree[p].sum=tree[LC(p)].sum+tree[RC(p)].sum;
} void build(int p,int l,int r){
tree[p].l=l;
tree[p].r=r;
if(l==r){
tree[p].sum=;
return;
}
build(LC(p),l,MID(l,r));
build(RC(p),MID(l,r)+,r);
pushup(p);
} void update(int p,int l,int r){
if(l>tree[p].r||r<tree[p].l)
return;
if(x<=)
return;
if(l<=tree[p].l&&r>=tree[p].r){
if(tree[p].sum==)
return;
//找到全空区间
if(x>=tree[p].sum&&tree[p].sum==tree[p].r-tree[p].l+){
if(flag==){
Start=tree[p].l;
flag++;
}
x-=tree[p].sum;
tree[p].sum=;
End=tree[p].r;
return;
}
}
pushdown(p);
update(LC(p),l,r);
update(RC(p),l,r);
pushup(p);
} void query(int p,int l,int r){
if(l>tree[p].r||r<tree[p].l)
return;
if(l<=tree[p].l&&r>=tree[p].r){
ans+=tree[p].r-tree[p].l+-tree[p].sum;
tree[p].sum=tree[p].r-tree[p].l+;
return;
}
pushdown(p);
query(LC(p),l,r);
query(RC(p),l,r);
pushup(p);
} int main(){
int T;
scanf("%d",&T);
while(T--){
int n,q;
scanf("%d%d",&n,&q);
build(,,n-);
while(q--){
int op;
scanf("%d",&op);
if(op==){
int l;
scanf("%d%d",&l,&x);
flag=;
update(,l,n-);
if(flag==)
printf("Can not put any one.\n");
else
printf("%d %d\n",Start,End);
}
else{
int l,r;
scanf("%d%d",&l,&r);
ans=;
query(,l,r);
printf("%d\n",ans);
}
}
printf("\n");
}
return ;
}

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 (2013多校第二场线段树)

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

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

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

  5. hdu4614 Vases and Flowers 线段树+二分

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意: 给你N个花瓶,编号是0  到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花. ...

  6. hdu4614 Vases and Flowers 线段树

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

  7. hdu 1754 I Hate It (线段树求区间最值)

    HDU1754 I Hate It Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u D ...

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

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

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

随机推荐

  1. php 阿拉伯数字转中文

    function numToWord($num){$chiNum = array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九');$chiUni = ...

  2. 全面支持Angular2的Web后台Bootstrap模板Sing App - Web & Angular 2.0 Dashboard

    在线预览 Sing App v3.3.0 (包含Angular 2.0版本实现) 现在,本模板完全支持Angular2.0版本啦. Sing Web App 是由专业前端工程师采用行业内流行的技术构建 ...

  3. webpack 4.x使用总结

    1.webpack 全局安装 npm install -g webpack 2.创建项目 比如文件夹是webpackdemo cd到webpackdemo文件夹下,执行: npm init 和 npm ...

  4. idea plugin 插件开发之检测文件修改

    实现 ApplicationComponent,BulkFileListener 接口,当然由于是 ApplicationComponent,因此需要在 plugin.xml 加上相关配置. plug ...

  5. 浅谈cocosd之autorelease\retain\release的理解

    三种情况,引出问题:   1) new出来的对象需要释放,而释放时,如果有其他人引用了这个对象,再次使用这个对象时,则会出现野指针情况. ==> 于是出现了引用计数的释放管理机制. 2) 对于一 ...

  6. python 字符串前缀u, r, b小结

    http://note.youdao.com/noteshare?id=a0da9c2d044d270fa8cb162b932c47e8

  7. Rabbitmq--topic

    一.前言 前面讲到direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求.topic类型的Exchan ...

  8. jeecms上传文件限制导致413-Request Entity Too Large

    1:spring mvc 上传限制大小  配置是否允许在上传文件的大小 <bean id="multipartResolver" class="org.spring ...

  9. libxml2在mingw下编译

    1.配置MingW路径,在环境变量path中加入/mingw32/bin2.解压libxml,进入win32目录3.记事本打开configure.js,找到var compiler = "m ...

  10. Redis 安装碰到问题

    一 make 报错 1. 出现如下错误 : cd src && make all make[1]: Entering directory '/xx/xx/redis-x.x.x/src ...