先看标签。线段树,树状数组(滚蛋),贪心(海星),所以选择贪心做;
(话说他想要疲劳值最大直接一直走不就行了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]));//两种情况 } }