• 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
    ", sum_w[root], sum_v[root]);
    	return 0;
    	}
    
  • 相关阅读:
    HTML导航条的制作
    图片样式加hover特效
    用表格制作商品购买页面--(table)
    CSS-盒子模型
    一些常见css样式加选择器
    css的一些样式
    HTML基本代码
    element-ui的tab切换同步步骤条 字符串转数字 数字转字符串
    vuex相关知识笔记
    js: 数组方法(中级)
  • 原文地址:https://www.cnblogs.com/Tony-Double-Sky/p/9839723.html
Copyright © 2020-2023  润新知