P2073 送花
P2073 送花
题目背景
小明准备给小红送一束花,以表达他对小红的爱意。他在花店看中了一些花,准备用它们包成花束。
题目描述
这些花都很漂亮,每朵花有一个美丽值W,价格为C。
小明一开始有一个空的花束,他不断地向里面添加花。他有以下几种操作:
操作 含义
1 W C 添加一朵美丽值为W,价格为C的花。
3 小明觉得当前花束中最便宜的一朵花太廉价,不适合送给小红,所以删除最便宜的一朵花。
2 小明觉得当前花束中最贵的一朵花太贵,他心疼自己的钱,所以删除最贵的一朵花。
-1 完成添加与删除,开始包装花束
若删除操作时没有花,则跳过删除操作。
如果加入的花朵价格已经与花束中已有花朵价格重复,则这一朵花不能加入花束。
请你帮小明写一个程序,计算出开始包装花束时,花束中所有花的美丽值的总和,以及小明需要为花束付出的总价格。
调试日志: 加粗第二处
错误日志: 加粗第一处
Solution
用这题练一下 \(Treap\)
平衡树的话就是板题了没啥好说了注意题目坑点(还有个坑是操作2、3的顺序题目给出是反过来的)
口胡一下码量少点的我的做法吧
堆 + 懒惰删除法
维护一个大根堆和一个小根堆, 堆内元素有三个值: 价钱、美丽值、 给他编的号
两个堆内元素相同, 以价钱为关键字排序, 以删除贵的为例:
开一个数组 \(ex[maxn]\) 维护这个值是否被删除过
删除堆顶, 标记其编号为被删除
下次删除小的值时取出堆顶, 若有标记则继续取出, 直到没有标记为止
这就是懒惰删除法
Code(Treap)
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#define LL long long
#define REP(i, x, y) for(LL i = (x);i <= (y);i++)
using namespace std;
LL RD(){
LL out = 0,flag = 1;char c = getchar();
while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
return flag * out;
}
const LL maxn = 200019, INF = 1e9;
LL ch[maxn][2], tot, root;
LL dat[maxn], val[maxn], W[maxn];
LL sum_v[maxn], sum_w[maxn];
LL size[maxn], cnt[maxn];
LL New(LL v, LL w){
dat[++tot] = rand();
val[tot] = sum_v[tot] = v;
W[tot] = sum_w[tot] = w;
size[tot] = cnt[tot] = 1;
ch[tot][0] = ch[tot][1] = 0;
return tot;
}
void pushup(LL id){
size[id] = size[ch[id][0]] + size[ch[id][1]] + cnt[id];
sum_v[id] = sum_v[ch[id][0]] + sum_v[ch[id][1]] + val[id];
sum_w[id] = sum_w[ch[id][0]] + sum_w[ch[id][1]] + W[id];
}
void build(){
root = New(-INF, -INF);
ch[root][1] = New(INF, INF);
pushup(root);
}
void Rotate(LL &id, LL d){
LL temp = ch[id][d ^ 1];
ch[id][d ^ 1] = ch[temp][d];
ch[temp][d] = id;
id = temp;
pushup(ch[id][d]), pushup(id);
}
void insert(LL &id, LL v, LL w){
if(!id){id = New(v, w);return ;}
if(val[id] == v);
else{
LL d = v < val[id] ? 0 : 1;
insert(ch[id][d], v, w);
if(dat[id] < dat[ch[id][d]])Rotate(id, d ^ 1);
}
pushup(id);
}
void Remove(LL &id, LL v){
if(!id)return ;
if(val[id] == v){
if(cnt[id] > 1){cnt[id]--, pushup(id);return ;}
if(ch[id][0] || ch[id][1]){
if(!ch[id][1] || dat[ch[id][0]] > dat[ch[id][1]])
Rotate(id, 1), Remove(ch[id][1], v);
else Rotate(id, 0), Remove(ch[id][0], v);
pushup(id);
}
else id = 0;
return ;
}
v < val[id] ? Remove(ch[id][0], v) : Remove(ch[id][1], v);
pushup(id);
}
LL get_val_by_rank(LL id, LL rank){
if(!id)return INF;
if(rank <= size[ch[id][0]])return get_val_by_rank(ch[id][0], rank);
else if(rank <= size[ch[id][0]] + cnt[id])return val[id];
else return get_val_by_rank(ch[id][1], rank - size[ch[id][0]] - cnt[id]);
}
int main(){
build();
while(1){
LL cmd = RD();
if(cmd == 1){
LL w = RD(), v = RD();
insert(root, v, w);
}
else if(cmd == 3){
if(size[root] == 2)continue;
LL v = get_val_by_rank(root, 2);
Remove(root, v);
}
else if(cmd == 2){
if(size[root] == 2)continue;
LL v = get_val_by_rank(root, size[root] - 1);
Remove(root, v);
}
else if(cmd == -1)break;
}
printf("%lld %lld\n", sum_w[root], sum_v[root]);
return 0;
}
P2073 送花的更多相关文章
- 【洛谷】【treap/堆】P2073 送花
[题目描述:] 这些花都很漂亮,每朵花有一个美丽值W,价格为C. 小明一开始有一个空的花束,他不断地向里面添加花.他有以下几种操作: 操作 含义 1 W C 添加一朵美丽值为W,价格为C的花. 3 小 ...
- 洛谷P2073 送花 [2017年6月计划 线段树01]
P2073 送花 题目背景 小明准备给小红送一束花,以表达他对小红的爱意.他在花店看中了一些花,准备用它们包成花束. 题目描述 这些花都很漂亮,每朵花有一个美丽值W,价格为C. 小明一开始有一个空的花 ...
- [洛谷P2073] 送花
送花 题目背景 小明准备给小红送一束花,以表达他对小红的爱意.他在花店看中了一些花,准备用它们包成花束. 题目描述 这些花都很漂亮,每朵花有一个美丽值W,价格为C. 小明一开始有一个空的花束,他不断地 ...
- 洛谷 P2073 送花【Treap】题解+AC代码
题目背景 小明准备给小红送一束花,以表达他对小红的爱意.他在花店看中了一些花,准备用它们包成花束. 题目描述 这些花都很漂亮,每朵花有一个美丽值W,价格为C. 小明一开始有一个空的花束,他不断地向里面 ...
- 【题解】Luogu P2073 送花
原题传送门 这题需要用到Splay 我们用一棵splay维护金钱 考虑c<=1000000 我们珂以把每种价格现在对应的美丽值存在一个a数组中 这样讲有珂能不太清楚qaq,还是对着操作一个一个讲 ...
- luogu P2073 送花 线段树
思路&心路 一眼认定沙比提 写的比较慢,写了1小时吧 开心的交上去 卧槽,只有20? 不服不服,拿着题解的代码去对拍 Emma,<100没问题 100000数据错了,还只是错了一个数据 ...
- 洛谷 P2073 送花
这题其实可以用vector水掉! 定义: 记住要用结构体(c为价格,x为美丽值)! 以c排序. struct Node { int x,c; bool operator < (const &am ...
- Luogu P2073 送花 set
这题...一眼set...但是打了一会儿.. 记录一下每个价格对应的美丽度,顺便充当vis数组,如果美丽度不为0,说明set里已经有了... 删除好说,删*s.begin()和*--s.end()就好 ...
- Luogu P2073 送花
权值线段树的模板题 然而AC后才发现,可以用\(\tt{set}\)水过-- 权值线段树类似于用线段树来实现平衡树的一些操作,代码实现还是比较方便的 #include<iostream> ...
随机推荐
- Execute SQL Task 如何返回结果数据集
Execute Sql Task的Result DataSet 主要有以下四种,当Execute Sql Task返回结果之后,需要使用SSIS Variable 来接收数据. 例子中使用的数据表代码 ...
- Shiro安全框架学习笔记
一.Shiro框架简单介绍 Apache Shiro是Java的一个安全框架,旨在简化身份验证和授权.Shiro在JavaSE和JavaEE项目中都可以使用.它主要用来处理身份认证,授权,企业会话管理 ...
- (幼儿园毕业)Javascript小学级随机生成四则运算
软件工程第二次结对作业四则运算自动生成器网页版 一.题目要求 本次作业要求两个人合作完成,驾驶员和导航员角色自定,鼓励大家在工作期间角色随时互换,这里会布置两个题目,请各组成员根据自己的爱好任选一题. ...
- CSS技巧收集——巧用滤镜
最近暴雪一款叫<守望先锋>的游戏火到不行,身边很多人都深受其毒害,虽然博主自己没有买(穷),但是耳濡目染也了解了个大概. 由于之前大致学习了一下 css 滤镜的各种用法,所以心血来潮结合二 ...
- html5实现拖拽上传头像
1. 将客户端(本地电脑)中的图片拖到网页中 要点: html5 拖放, FileReader html: <div id="container" ondrop=" ...
- PAT甲题题解-1073. Scientific Notation (20)-字符串处理
题意:给出科学计数法的格式的数字A,要求输出普通数字表示法,所有有效位都被保留,包括末尾的0. 分两种情况,一种E+,一种E-.具体情况具体分析╮(╯_╰)╭ #include <iostrea ...
- 12.23daily_scrum
今天大家的工作重心在调试过程中,以便及时地发现和解决在调试过程中出现的问题和漏洞,悬浮窗测试工作也已经展开,主要集中在边缘设计代码的测试部分,具体工作如下: 具体工作: 小组成员 今日任务 明日任务 ...
- 【Beta阶段】第一次Scrum Meeting!
本次会议为第一次Scrum Meeting会议~ 会议时长:20分 会议地点:依旧是7公寓1楼会客室 昨日任务一览 明日任务一览 刘乾 预定任务:(未完成)#128 学习如何在Github上自动构 ...
- process.tar.gz
exec1.c #include <stdio.h> #include <unistd.h> int main() { char *arglist[3]; arglist[0] ...
- C++:继承访问属性(public/protected/private)
• 公有继承(public) 公有继承在C++中是最常用的一种继承方式,我们先来看一个示例: #include<iostream> using namespace std; class F ...