[Luogu2073]送花

题面
题目背景
小明准备给小红送一束花,以表达他对小红的爱意。他在花店看中了一些花,准备用它们包成花束。
题目描述
这些花都很漂亮,每朵花有一个美丽值W,价格为C。
小明一开始有一个空的花束,他不断地向里面添加花。他有以下几种操作:
操作 含义
1 W C 添加一朵美丽值为W,价格为C的花。
3 小明觉得当前花束中最便宜的一朵花太廉价,不适合送给小红,所以删除最便宜的一朵花。
2 小明觉得当前花束中最贵的一朵花太贵,他心疼自己的钱,所以删除最贵的一朵花。
-1 完成添加与删除,开始包装花束
若删除操作时没有花,则跳过删除操作。
如果加入的花朵价格已经与花束中已有花朵价格重复,则这一朵花不能加入花束。
请你帮小明写一个程序,计算出开始包装花束时,花束中所有花的美丽值的总和,以及小明需要为花束付出的总价格。
输入输出格式
输入格式:
若干行,每行一个操作,以-1结束。
输出格式:
一行,两个空格隔开的正整数表示开始包装花束时,花束中所有花的美丽值的总和。以及小明需要为花束付出的总价格。
输入输出样例
输入样例#1:

1 1 1
1 2 5
2
1 3 3
3
1 5 2
-1

输出样例#1:

8 5

说明
对于20%数据,操作数<=100,1<=W,C<=1000。
对于全部数据,操作数<=100000,1<=W,C<=1000000。

题解

这不是splay傻逼板子题吗?
注意题面操作2和3是反的呵
然后就是板子了
然而我还是WA了一次

code

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
const int N = 100005;
int fa[N],ls[N],rs[N],val[N],W[N],root,tot,opt;
ll price,beauty;
void R_rotate(int x)
{
    int y=fa[x],z=fa[y];
    ls[y]=rs[x];
    if (rs[x]) fa[rs[x]]=y;
    fa[x]=z;
    if (z) if (y==ls[z]) ls[z]=x;else rs[z]=x;
    rs[x]=y;fa[y]=x;
}
void L_rotate(int x)
{
    int y=fa[x],z=fa[y];
    rs[y]=ls[x];
    if (ls[x]) fa[ls[x]]=y;
    fa[x]=z;
    if (z) if (y==ls[z]) ls[z]=x;else rs[z]=x;
    ls[x]=y;fa[y]=x;
}
void splay(int x)
{
    while (fa[x])
    {
        int y=fa[x],z=fa[y];
        if (!z)
            if (x==ls[y]) R_rotate(x);
            else L_rotate(x);
        else
            if (y==ls[z])
                if (x==ls[y]) R_rotate(y),R_rotate(x);
                else L_rotate(x),R_rotate(x);
            else
                if (x==ls[y]) R_rotate(x),L_rotate(x);
                else L_rotate(y),L_rotate(x);
    }
    root=x;
}
void Insert()
{
    int x=root,v,w;scanf("%d %d",&w,&v);
    if (!root)
    {
        root=++tot;
        val[root]=v;W[root]=w;
        return;
    }
    while (1)
    {
        if (v<val[x])
        {
            if (!ls[x])
            {
                ls[x]=++tot;
                val[tot]=v;W[tot]=w;
                fa[tot]=x;
                splay(tot);
                return;
            }
            x=ls[x];
        }
        else if (v>val[x])
        {
            if (!rs[x])
            {
                rs[x]=++tot;
                val[tot]=v;W[tot]=w;
                fa[tot]=x;
                splay(tot);
                return;
            }
            x=rs[x];
        }
        else if (v==val[x]) return;
    }
}
void Del_Max()
{
    int x=root;
    if (!rs[x])
    {
        fa[root=ls[x]]=0;
        return;
    }
    while (rs[x]) x=rs[x];
    rs[fa[x]]=ls[x];
    if (ls[x]) fa[ls[x]]=fa[x];
}
void Del_Min()
{
    int x=root;
    if (!ls[x])
    {
        fa[root=rs[x]]=0;
        return;
    }
    while (ls[x]) x=ls[x];
    ls[fa[x]]=rs[x];
    if (rs[x]) fa[rs[x]]=fa[x];
}
void dfs(int x)
{
    price+=val[x];beauty+=W[x];
    if (ls[x]) dfs(ls[x]);
    if (rs[x]) dfs(rs[x]);
}
int main()
{
    while (1)
    {
        scanf("%d",&opt);
        if (opt==-1) break;
        if (opt==1) Insert();
        if (opt==2) Del_Max();
        if (opt==3) Del_Min();
    }
    dfs(root);
    printf("%lld %lld\n",beauty,price);
    return 0;
}

转载于:https://www.cnblogs.com/zhoushuyu/p/8167931.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值