BestCoder Round #91 1001 (HDU 6011 Lotus and Characters) 1002 (HDU 6012 Lotus and Horticulture)

HDU 6011 Lotus and Characters(贪心)

题意

有n种字母,每个都有价值和使用个数限制,问这些字母组合成的字符串的最大价值是多少,字母的价值有可能是负数,字符串价值的计算方式为当前下标和对应字母价值的累乘和

思路

首先价值越高的越应该放到后面,按价值排序,但是有几个小坑

  • 价值为负的字母可能也可以加进去 例如 -1,-1 ,-1 ,2 ,2,2
  • 一个字母可以不全部用完

所以应该按照价值从后往前放,直到放置新的字母不会更优,用一个变量来保存累计和

代码

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
const int INF=0x3f3f3f3f;
const int maxn=3e5+50;
const int Mod=1000000007;
const double PI=acos(-1);
typedef long long ll;
typedef unsigned int ui;
using namespace std;

int n;

struct Node{
    int x,v;
    bool operator<(const Node &r)const{
        return v>r.v;
    }
};

Node s[maxn];

int work(){
    int tot=0,ret=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<s[i].x;j++){
            tot+=s[i].v;
            if(tot<0) return ret;
            ret+=tot;
        }
    }
    return ret;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%d %d",&s[i].v,&s[i].x);
        }
        sort(s,s+n);
        printf("%d\n",work());
    }
    return 0;
}

HDU 6012 Lotus and Horticulture

题意

有n个植物,每个植物的合适生长温度区间为 [l,r] ,合适时可以提供 ai 研究价值,当高于r时可以提供 bi 研究价值,当低于l时可以提供 ci 研究价值,温度可以是任意实数,任意选择能使总的研究价值最大的温度,输出最大的研究价值

思路

话说我直到快结束才看懂任意实数的意思,怪不得看不懂样例。。
首先,区间是左闭右闭的
对于一个植物来说,会引起价值变化的只有:

  • 温度低于左端点
  • 温度进入区间
  • 温度高于右端点
    我们假设温度从低到高变化,那么价值的变化范围就是

  • 一开始 ci

  • 到达左端点加上 aici
  • 离开右端点加上 biai

因此我们只需要一开始将温度设为最低,然后从左往右扫描这些会引起这些价值变化的点即可

需要注意的是,因为温度可以是任意实数(例如距离左端点0.5),可以将所有温度区间都扩大一倍,这样只需要处理整数

代码

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
const int INF=0x3f3f3f3f;
const int maxn=3e5+50;
const int Mod=1000000007;
const double PI=acos(-1);
typedef long long ll;
typedef unsigned int ui;
using namespace std;

int n;

struct Node{
    int add,t;
    bool operator<(const Node &r)const{
        return t<r.t;
    }

    Node() {}

    Node(int t,int add){
        this->t=t;
        this->add=add;
    }

};
Node nd[maxn*4];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
#endif
    int T;
    scanf("%d",&T);
    while(T--){
        int cnt=0;
        scanf("%d",&n);
        int l,r,a,b,c;
        ll ans=0;
        for(int i=0;i<n;i++){
            scanf("%d %d %d %d %d",&l,&r,&a,&b,&c);
            l*=2; r*=2;
            nd[cnt++]=Node(l,a-c);
            nd[cnt++]=Node(r+1,b-a);
            ans+=c;
        }
        ll tmp=ans;
        sort(nd,nd+cnt);
        for(int i=0;i<cnt;i++){
            tmp+=nd[i].add;
            if(i<cnt && nd[i].t!=nd[i+1].t)
                ans=max(ans,tmp);
        }
        ans=max(ans,tmp);
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值