洛谷 P2672 推销员(贪心,模拟)

传送门


解题思路

第一种

 

对于选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 }
第一种
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<queue>
 5 using namespace std;
 6 const int maxn=100005;
 7 int n;
 8 long long ans;
 9 struct node{
10     int s;
11     int a;
12     bool operator<(const node &p) const{
13         return 2*s+a<p.s*2+p.a;
14     }
15 }d[maxn]; 
16 priority_queue<int> q1;
17 priority_queue<node> q2; 
18 void shuchu() {
19     printf("%lld\n",ans);
20 }
21 int main(){
22     cin>>n;
23     for(int i=1;i<=n;i++){
24         scanf("%d",&d[i].s);
25     }
26     for(int i=1;i<=n;i++){
27         scanf("%d",&d[i].a);
28     }
29     for(int i=1;i<=n;i++){
30         q2.push(d[i]);
31     }
32     int now=0;
33     for(int i=1;i<=n;i++){
34         node d2;
35         if(!q2.empty()){
36             d2=q2.top();
37             while(d2.s<now&&!q2.empty()) q2.pop(),d2=q2.top();
38         }
39         if(q1.empty()){
40             node d2=q2.top();
41             q2.pop();
42             now=d2.s;
43             ans+=d2.a+2*d2.s-2*now;
44             shuchu();
45             continue;
46         }
47         if(q2.empty()){
48             int d1=q1.top();
49             q1.pop();
50             ans+=d1;
51             shuchu();
52             continue;
53         }
54         int d1=q1.top();
55         int d22=d2.a+2*d2.s-2*now;
56         if(d1>d22){
57             q1.pop();
58             ans+=d1;
59         }else{
60             q2.pop();
61             now=d2.s;
62             ans+=d22;
63         }
64         shuchu();
65     }
66     return 0;
67 }
第二种

//NOIP2015普及组t4

posted @ 2019-10-29 23:06  尹昱钦  阅读(324)  评论(0编辑  收藏  举报