[NOIP 2015 普及组] 推销员

阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有 \(N\) 家住户,第 \(i\) 家住户到入口的距离为 \(S_i\) 米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的 \(X\) 家住户推销产品,然后再原路走出去。阿明每走 \(1\) 米就会积累 \(1\) 点疲劳值,向第 \(i\) 家住户推销产品会积累 \(A_i\) 点疲劳值。阿明是工作狂,他想知道,对于不同的 \(X\),在不走多余的路的前提下,他最多可以积累多少点疲劳值。
对于 \(60\%\) 的数据,\(1 \le N \le 1000\)
对于 \(100\%\) 的数据,\(1 \le N \le 100000\)

先考虑 \(60\%\) 的数据,我们可以设到达的最远处为 \(p\)。显然当前最优解是从前 \(p-1\) 中选 \(X\)\(A_i\) 最大的,再加上 \(A_p\) 以及往返的疲劳值。复杂度为 \(O(n^2)\)

然后我们可以发现最优解一定包含最大的 \(X-1\)\(A_i\)

证明:最大的几个分别为 \(B_1,B_2,\dots,B_{X-1}\),最优解为 \(C_1,C_2,C_3,\dots C_{X}\)\(C\) 不包含 \(B_{i}\)\(C_X\) 最大。那么一定存在 \(C_j\) 使得 \(A_{C_j}<A_{B_i}\)\(j<X\)。用 \(B_i\) 代替 \(C_j\),答案一定不i会变劣。

最优解中可能不包含第 \(X\) 大的 \(A_i\),因为我们可以选一个更远的住户是走路的疲劳值变大,此时该住户要比前 \(X\) 大的住户距巷口更远,然后用该住户替代 \(X\) 大的 \(A_i\) 即可。寻找这个住户可以用后缀最大值来找。复杂度 \(O(nlogn)\)

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+9;
int a[N],b[N],c[N],n,idx[N];
bool cmp(int x,int y){return b[x]>b[y];}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i],idx[i]=i;
    for(int i=1;i<=n;i++)cin>>b[i],c[i]=a[i]*2+b[i];
    for(int i=n-1;i;i--)c[i]=max(c[i],c[i+1]);
    sort(idx+1,idx+n+1,cmp);
    for(int k=1,sum=0,x=0;k<=n;k++){
        sum+=b[idx[k]],x=max(x,idx[k]);
        int ans=sum+a[x]*2;
        int cur=c[x+1]+sum-b[idx[k]];
        cout<<max(ans,cur)<<endl;
    }
    return 0;
}
posted @ 2025-06-12 17:53  fzrcy  阅读(16)  评论(0)    收藏  举报