P2672推销员

传送

很抱歉之前用错误的思路写了一篇题解ρωρ

先说一下之前的思路。

对于每个住户,求出它的s[i]*2+a[i],寻找最大的住户m,然后按照a排序,如果m在前x大的住户里面,就选择前x大的住户,从中选择最大的s,计算答案。否则选择权值前x-1大的住户和m。

but这个是错的!!!!

hack数据:

1 5 6

3 5 2

正确答案:15 19 22

上述思路的答案:15 18 22

第二个按照上述思路的选法:选择第1,2户。

正解选法:选择第2,3户。

错误思路的代码:

#include<bits/stdc++.h>
using namespace std;
int n,sum[100009],ma[400009];
struct zh{
    int bh,l,p,q;
}r[100009];
int read()
{
    char ch=getchar();
    int x=0;bool f=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    f?x=-x:x=x;
    return x;
}
bool cmp1(zh a,zh b)
{
    return a.p>b.p;
}
int main()
{
    int maxn=0,maxi;
    n=read();int m;
    for(int i=1;i<=n;i++)
     r[i].l=read(),r[i].bh=i;
    for(int i=1;i<=n;i++)
     {
         r[i].p=read();
         r[i].q=r[i].l*2+r[i].p;
         if(r[i].q>maxn)
          maxn=r[i].q,maxi=r[i].bh;
     }
     m=r[n].l;
     sort(r+1,r+1+n,cmp1);
     for(int i=1;i<=n;i++)
       sum[i]=sum[i-1]+r[i].p,ma[i]=max(ma[i-1],r[i].l);
     int mi;
     for(int i=1;i<=n;i++)
     {
         if(r[i].bh==maxi)
         {
             mi=i;
             break;
        }
     }
     printf("%d\n",maxn);
     for(int i=2;i<n;i++)
     {int ren=0,lu=r[mi].l*2;
         if(mi<=i)
         {
             ren=sum[i];
         if(ma[i]>r[mi].l)lu=ma[i]*2;
         int ans=ren+lu;
         printf("%d\n",ans);
        }
        else
        {    ren=r[mi].p+sum[i-1];
         if(ma[i-1]>r[mi].l)lu=ma[i-1]*2;
         int ans=ren+lu;
         printf("%d\n",ans);
        }
     }
     int ans=0;
     for(int i=1;i<=n;i++)
       ans+=r[i].p;  
       ans+=m*2;
       printf("%d\n",ans);
}
它是个错的QAQ

正确的思路是什么鸭?窝也不会鸭~来让我们仔(fan)细(fan)思(ti)考(jie)

先来说一下上面的思路错在哪里。

上面对于每个x,都有一种确定的方案(选前x个或者选前x-1个)。但是我们不知道另一种方案是否比我们确定的这个方案要优。

所以我们把上面的两种选法比较一下。

先按照a从大到小排序

用qaq[i]来记录i个住户里面最大的a[i]+s[i]*2(排序后),sum[i]是排序后的前缀和,ma[i]是排序后前i个中的最大的s,则ansi=max(sum[x]+ma[i]*2,sum[x-1]+qaq[x])

为什么qaq是记录i个住户的信息呢?

因为后i个住户的a会小,但是s可能会很大。这里是考虑s对ans的影响

代码:

#include<bits/stdc++.h>
using namespace std;
int n,sum[100009],ma[400009],qaq[400009];
struct zh{
    int bh,l,p,q;
}r[100009];
int read()
{
    char ch=getchar();
    int x=0;bool f=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+(ch^48);
        ch=getchar();
    }
    f?x=-x:x=x;
    return x;
}
bool cmp1(zh a,zh b)
{
    return a.p>b.p;
}
int main()
{
    int maxn=0,maxi;
    n=read();int m;
    for(int i=1;i<=n;i++)
     r[i].l=read(),r[i].bh=i;
    for(int i=1;i<=n;i++)
     {
         r[i].p=read();
         r[i].q=r[i].l*2+r[i].p;
         if(r[i].q>maxn)
          maxn=r[i].q,maxi=r[i].bh;
     }
     m=r[n].l;
     sort(r+1,r+1+n,cmp1);
     for(int i=1;i<=n;i++)
       sum[i]=sum[i-1]+r[i].p,ma[i]=max(ma[i-1],r[i].l);
     qaq[n]=r[n].l*2+r[n].p;
     for(int i=n-1;i>=1;i--)
        qaq[i]=max(qaq[i+1],r[i].l*2+r[i].p);
     
     printf("%d\n",maxn);
     for(int i=2;i<n;i++)
     {
        int ans=max(sum[i]+ma[i]*2,sum[i-1]+qaq[i]);
        printf("%d\n",ans);
     }
     int ans=0;
     for(int i=1;i<=n;i++)
       ans+=r[i].p;  
       ans+=m*2;
       printf("%d\n",ans);
}
它终于对了

 

posted @ 2019-07-03 10:58  千载煜  阅读(115)  评论(0编辑  收藏  举报