洛谷P2672 推销员

先看标签。线段树,树状数组(滚蛋),贪心(海星),所以选择贪心做;

话说他想要疲劳值最大直接一直走不就行了qwq

考虑虑i的最大疲劳值一定是选择i个val最大的或者是i-1个val最大的和一个s较大的(之所以不是最大的是因为val还会产生影响) 

所以我们把这些住宅按照val排序

在选择i个val最大的情况下,产生的疲劳值就是前i个val的和加上两倍的最大距离(前i个物品之间的)

在选择i-1个val最大的和一个s较大的情况下,我们考虑从后往前枚举2*s+val的最大值,然后在加上前i-1个val的和就可以了

所以我们考虑预处理一下,设h[i]表示后i个2*s+val的最大值 ,q[i]表示前i个距离最大值,sum[i]表示前i个val的和

最后第i项的答案就是max(sum[i-1]+h[i],sum[i]+2*q[i])了

代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

inline int read()
{
    int ans=0;
    char last=' ',ch=getchar();
    while(ch<'0'||ch>'9') last=ch,ch=getchar();
    while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar();
    if(last=='-') ans=-ans;
    return ans;
}

//考虑i的最大价值一定是选择所有val最大的或者是i-1个val最大的和一个s较大的 

struct home
{
    int s,val;
}a[100005];

int n;

inline bool cmp(home a,home b)
{
    return a.val>b.val;
}

int sum[100005],q[100005],h[100005];

int main()
{
    n=read();
    for(int i=1;i<=n;i++) a[i].s=read();
    for(int i=1;i<=n;i++) a[i].val=read();
    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].val);//后i个2*a[i].s+a[i].val的最大值 
    }
    for(int i=1;i<=n;i++)
    {
        q[i]=max(q[i-1],a[i].s);//前i个距离最大值 
        sum[i]=sum[i-1]+a[i].val;//前i个val的和 
    }
    for(int i=1;i<=n;i++)
    {
        printf("%d
",max(sum[i-1]+h[i],sum[i]+2*q[i]));//两种情况 
    }
    
}
原文地址:https://www.cnblogs.com/lcezych/p/11124693.html