洛谷 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