推销员

题目描述

阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有NNN家住户,第iii家住户到入口的距离为SiS_iSi米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的XXX家住户推销产品,然后再原路走出去。

阿明每走111米就会积累111点疲劳值,向第iii家住户推销产品会积累AiA_iAi点疲劳值。阿明是工作狂,他想知道,对于不同的XXX,在不走多余的路的前提下,他最多可以积累多少点疲劳值。

输入输出格式

输入格式:

 

第一行有一个正整数NNN,表示螺丝街住户的数量。

接下来的一行有NNN个正整数,其中第iii个整数SiS_iSi表示第iii家住户到入口的距离。数据保证S1≤S2≤…≤Sn<108S_1≤S_2≤…≤S_n<10^8S1S2Sn<108。

接下来的一行有NNN个正整数,其中第iii个整数AiA_iAi表示向第iii户住户推销产品会积累的疲劳值。数据保证Ai<1000A_i<1000Ai<1000。

 

输出格式:

 

输出NNN行,每行一个正整数,第i行整数表示当X=iX=iX=i时,阿明最多积累的疲劳值。

分析:

我们先把数组按照a排序

我们用sum[i]表示a数组的前i项的和,q[i]表示s数组的前i项的最大值,h[i]表示a[i]*2+s[i]后i项的最大值,对于每个x,他的答案就是max(sum[x]+2*q[x],sum[x-1]+h[x])

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
struct home{
    int s,v;
}a[100010];
int q[100010];
int h[100010],qm[100010];
int n;
bool cmp(home a,home b)
{
    return a.v>b.v;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].s);
    }
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i].v);
    }
    sort(a+1,a+1+n,cmp);
    for (int i=n;i>=1;i--)
    {
        h[i]=max(h[i+1],2*a[i].s+a[i].v);
    }
    for (int i=1;i<=n;i++)
    {
        qm[i]=max(qm[i-1],a[i].s);
    }
    for (int i=1;i<=n;i++)
        q[i]=q[i-1]+a[i].v;
    for (int i=1;i<=n;i++)
    {
        printf("%d
",max(q[i-1]+h[i],q[i]+2*qm[i]));
    }
} 

  

原文地址:https://www.cnblogs.com/chen-1/p/10046628.html