• P2073 送花


    题目背景

    小明准备给小红送一束花,以表达他对小红的爱意。他在花店看中了一些花,准备用它们包成花束。

    题目描述

    这些花都很漂亮,每朵花有一个美丽值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。

    Solution:

      本题$c$保证只会出现一次且$cleq 10^6$,于是我们以$c$为关键字,维护花费和优美度,构建一棵权值线段树

      对于$1$操作,我们直接查询$c$节点是否有值,有就直接返回,否则就赋值。

      对于$2$操作,要删去最大值,则从完整区间开始,只要右子树有点或左子树无点则尽可能遍历右儿子,否则才遍历左儿子,将最后到达的叶子节点清$0$。

      对于$3$操作,要删去最小值,则从完整区间开始,只要左子树有点则尽可能遍历左儿子,否则才遍历右儿子,将最后到达的叶子节点清$0$。

      最后输出整个区间的总优美度和总花费就$OK$了。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define lson (l),(m),(rt<<1)
    #define rson (m+1),(r),(rt<<1|1)
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)>(b)?(b):(a))
    using namespace std;
    const int N=1e6+7,inf=2147483647;
    ll n,m,sum[N<<2],cost[N<<2],f,l=1,r=1e6,a;
    il int gi(){
        int a=0;char x=getchar();bool f=0;
        while((x<'0'||x>'9')&&x!='-')x=getchar();
        if(x=='-')x=getchar(),f=1;
        while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
        return f?-a:a;
    }
    il void pushup(int rt){
        cost[rt]=cost[rt<<1]+cost[rt<<1|1];
        sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    il void update(int k,int d,int l,int r,int rt){
        if(l==k&&r==k){
            if(cost[rt])return;
            sum[rt]=d,cost[rt]=k;return;
        }
        int m=l+r>>1;
        if(k<=m)update(k,d,lson);
        else update(k,d,rson);
        pushup(rt);
    }
    il void del(int l,int r,int rt,bool f){
        if(l==r){sum[rt]=cost[rt]=0;return;}
        int m=l+r>>1;
        if(f&&cost[rt<<1]&&cost[rt<<1|1])del(rson,f);
        else if(!cost[rt<<1])del(rson,f);
        else del(lson,f);
        pushup(rt);
    }
    int main(){
        int x,y;
        f=gi();
        while(f!=-1){
            if(f==1){x=gi(),y=gi();update(y,x,l,r,1);}
            if(f==2){del(l,r,1,1);}
            if(f==3){del(l,r,1,0);}
            f=gi();
        }
        cout<<sum[1]<<' '<<cost[1];
        return 0;
    }

     

      

  • 相关阅读:
    CSS中float与A标签的疑问
    常用的Css命名方式
    div css 盒子模型
    HTML初级教程 表单form
    Redis学习记录(二)
    Redis学习记录(一)
    Java源码——HashMap的源码分析及原理学习记录
    java编程基础——从上往下打印二叉树
    java编程基础——栈压入和弹出序列
    java基础编程——获取栈中的最小元素
  • 原文地址:https://www.cnblogs.com/five20/p/8969444.html
Copyright © 2020-2023  润新知