传送门


解题思路

第一种

 

对于选i家,很显然,a值前i-1家的一定会选,所以只需要考虑最后一家的选法。要么是选择a值第i大的(就不管s了),要么选择剩下的中s最大的。

我们把每一家的情况(s和a)存入几个结构体中,按照a的值从大到小排序,再用sum求出a的前缀和,用maxs[i]表示前i家中最大的s,用maxa[i]表示在i...n家中选一家的最大价值,即(s*2+a)的最大值。

然后对于要求的每一个i,ans[i]就是

  • 选a值最大的前i家
  • 选a值最大的前i-1家加上剩下的i...n家中贡献最大的那家

中的最大值,即

ans[i]=max(sum[i]+2*maxs[i],sum[i-1]+maxa[i]))。

第二种:

很显然,ans随着i的增大递增,所以用一个ans记录答案,每一次加上一个数。

对于每一次选择,可以分为两种情况,设距离最远的一家的地址为now:

  • 选择地址<now的a值最大的那一家k,对答案的贡献为a[k]
  • 选择地址>now的对答案贡献最大的那一家k,对答案的贡献为a[k]+2*(s[k]-now)

所以每次取max即可。

这里用两个大跟堆来实现比较方便。

q1存的是在now左面的点,q2存的是now右面的点。

如果更新右面的点,就q2弹出去一个,然后把q1中加入所有坐标在now和q2.top()的坐标之间的点,最后更新now的值。

如果更新的是左面的点,就q1弹出,q2不做处理。

这样,在每次取q2中的点时,就要先弹出所有坐标小于now的点。

AC代码

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cmath>
 4 #include<cstdio>
 5 using namespace std;
 6 const int maxn=100005;
 7 int n,maxs[maxn],maxa[maxn];
 8 struct node{
 9     int s,a;
10     bool operator <(const node &xx) {
11         return a>xx.a;
12     }
13 }x[maxn];
14 int sum[maxn];
15 int main()
16 {
17     cin>>n;
18     for(int i=1;i<=n;i++){
19         scanf("%d",&x[i].s);
20     }
21     for(int i=1;i<=n;i++){
22         scanf("%d",&x[i].a);
23     }
24     sort(x+1,x+n+1);
25     for(int i=1;i<=n;i++){
26         sum[i]=sum[i-1]+x[i].a;
27         maxs[i]=max(maxs[i-1],x[i].s);
28     }
29     for(int i=n;i>=1;i--){
30         maxa[i]=max(maxa[i+1],2*x[i].s+x[i].a);
31     }
32     for(int i=1;i<=n;i++){
33         printf("%d\n",max(sum[i]+2*maxs[i],sum[i-1]+maxa[i]));
34     }
35     return 0;
36 }
第一种

相关文章:

  • 2021-12-30
  • 2021-07-06
  • 2021-06-07
  • 2022-12-23
  • 2020-10-11
  • 2022-12-23
  • 2021-06-21
猜你喜欢
  • 2021-05-18
  • 2021-07-22
  • 2022-02-28
  • 2021-06-26
  • 2021-09-07
  • 2021-08-04
相关资源
相似解决方案