HDU 4614 Vases and Flowers(线段树+记录区间始末点或乱搞)
题目链接: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(线段树+记录区间始末点或乱搞)的更多相关文章
- HDU 4614 Vases and Flowers(线段树+二分)
题目链接 比赛的时候一直想用树状数组,但是树状数组区间更新之后,功能有局限性.线段树中的lz标记很强大,这个题的题意也挺纠结的. k = 1时,从a开始,插b个花,输出第一个插的位置,最后一个的位置, ...
- hdu 4614 Vases and Flowers 线段树
题目链接 一共n个盒子, 两种操作, 第一种是给出两个数x, y, 从第x个盒子开始放y朵花, 一个盒子只能放一朵, 如果某个盒子已经有了, 那么就跳过这个盒子放下面的盒子. 直到花放完了或者到了最后 ...
- HDU 4614 Vases and Flowers (2013多校第二场线段树)
题意摘自:http://blog.csdn.net/kdqzzxxcc/article/details/9474169 ORZZ 题意:给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每 ...
- HDU-4614 Vases and Flowers 线段树区间更新
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 线段树保存区间是否被覆盖以及区间的和即可,在询问的时候在线段树上二分查找就可以了...代码写得比 ...
- hdu4614 Vases and Flowers 线段树+二分
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4614 题意: 给你N个花瓶,编号是0 到 N - 1 ,初始状态花瓶是空的,每个花瓶最多插一朵花. ...
- 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 1754 I Hate It (线段树求区间最值)
HDU1754 I Hate It Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u D ...
- HDU 4614 Vases and Flowers(线段树+二分)
Vases and Flowers Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others ...
- 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 ...
随机推荐
- WildFly8(JBoss)默认web服务器-------Undertow
Java微服务框架之Undertow 一.Undertow简介: Undertow 是红帽公司(RedHat)的开源产品,是 WildFly8(JBoos) 默认的 Web 服务器. 官网API给出一 ...
- 洛谷 U14472 数据结构【比赛】 【差分数组 + 前缀和】
题目描述 蒟蒻Edt把这个问题交给了你 ---- 一个精通数据结构的大犇,由于是第一题,这个题没那么难.. edt 现在对于题目进行了如下的简化: 最开始的数组每个元素都是0 给出nnn,optopt ...
- BZOJ 2959: 长跑 解题报告
2959: 长跑 Description 某校开展了同学们喜闻乐见的阳光长跑活动.为了能"为祖国健康工作五十年",同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑 ...
- 洛谷 P1858 多人背包 解题报告
P1858 多人背包 题目描述 求01背包前k优解的价值和 输入输出格式 输入格式: 第一行三个数\(K\).\(V\).\(N\) 接下来每行两个数,表示体积和价值 输出格式: 前k优解的价值和 说 ...
- 【codechef】Children Trips
Portal -->CC_Children Trips Solution (英文题解看得真爽qwq不过写的好详细啊ovo) 首先这题有一个很重要的条件就是边权是\(1\)或者\(2\),所以虽然 ...
- 省选模拟赛 LYK loves rabbits(rabbits)
题目描述 LYK喜欢兔子,它在家中养了3只兔子. 有一天,兔子不堪寂寞玩起了游戏,3只兔子排成一排,分别站在a,b,c这3个位置. 游戏的规则是这样的,重复以下步骤k次:选择两个不同的兔子A和B,假如 ...
- DINSTINCT
DISTINCT是对结果集进行去重,有三点需要注意. 1.在大多数情况下(两者后面所跟的字段相同时),DISTINCT跟group by是等效的,此时DISTINCT可以看作group by的一个特例 ...
- Bootstrap3和Bootsrap4的区别
Bootstrap3和Bootstap4的区别 1.Bootsrap4 css文件减少了40%以上 2.Bootsrap4已经不支持IE8以及IOS 6的支持 3.多了些类好组件
- Drools规则引擎环境搭建
Drools 是一款基于Java 的开源规则引擎,所以在使用Drools 之前需要在开发机器上安装好JDK 环境,Drools5 要求的JDK 版本要在1.5 或以上. Drools5 提供了一个基于 ...
- 【CodeForces】866D. Buy Low Sell High
[题意]已知n天股价,每天可以买入一股或卖出一股或不作为,最后必须持0股,求最大收益. [算法]堆 贪心? [题解] 不作为思想:[不作为=买入再卖出] 根据不作为思想,可以推出中转站思想. 中转站思 ...