【洛谷2672】推销员

题面

阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有N家住户,第ii家住户到入口的距离为Si米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的X家住户推销产品,然后再原路走出去。  阿明每走1米就会积累1点疲劳值,向第ii家住户推销产品会积累Ai ​点疲劳值。阿明是工作狂,他想知道,对于不同的X,在不走多余的路的前提下,他最多可以积累多少点疲劳值。

分析

当时是搜线段树的题,想随便做一做,然后就选了一道提高-的涨涨信心

结果做着做着思路越来越偏,这是当时记事本上写的内心os(d是距离,c是推销花费,dmax最大,dcmax次大):

  我想先试着倒着做,最大的情况肯定是唯一的sum=dmax* 2+ segma c
  然后来减,试着减少推销一个住户,那减少的住户一定要是贡献最少的
  贡献少-->距离短or推销花费少
  如果距离短(短于最远距离),本来也就不会有任何的贡献,所以只需要找出推销花费最少的一个??
  sum-=c[i]即可
  那如果要修改最远距离呢?那sum=sum-dmax*2+dcmax*2-c[i],dmax=dcmax,好像就可以了?
  而且这个d好像可以
  所以要比较一下这两个哪个更小就ok了?

然后就开始用两个优先队列搞了,基本上算个模拟题了,好吧,一次A了,确实挺涨信心,可是我想做线段树啊!!!

后来根据第二组样例发现,如果说最远距离和推销花费最少的是同一户人家,特判一下,即拿最远距离和花费第二少比较。

然后看了一发线段树的题解,怎么这么复杂...算了算了另外找题

代码

#include<bits/stdc++.h>
using namespace std;
#define N 100100
#define ll long long
ll n,sum;
ll ans[N],vis[N];
struct email1
{
    ll ad,ac,aid;
}a[N];
struct email2 
{
    ll bd,bc,bid;
}b[N];
bool operator <(email1 x,email1 y)
{
    return x.ad<y.ad;
}
bool operator <(email2 x,email2 y)
{
    return x.bc>y.bc;
}
priority_queue<email1>qd;
priority_queue<email2>qc;

int main()
{
    scanf("%d",&n);
    for(ll i=1;i<=n;i++)
    {
        ll d;
        scanf("%lld",&d);
        a[i].ad=b[i].bd=d;
        a[i].aid=b[i].bid=i;
    }
    for(ll i=1;i<=n;i++)
    {
        ll c;
        scanf("%lld",&c);
        sum+=c;
        a[i].ac=b[i].bc=c;
        qc.push(b[i]);qd.push(a[i]);
    }
    email1 pos=qd.top();
    sum+=pos.ad*2;ans[n]=sum;
    for(ll i=1;i<=n-1;i++)
    {
        email1 d,d2;
        while(vis[qd.top().aid])qd.pop();d=qd.top();qd.pop();
        while(vis[qd.top().aid])qd.pop();d2=qd.top();
        email2 c,c2;
        while(vis[qc.top().bid])qc.pop();c=qc.top();qc.pop();
        while(vis[qc.top().bid])qc.pop();c2=qc.top();
        if(d.aid==c.bid)
        {
            if(d.ad*2+d.ac-d2.ad*2<c2.bc)
            {
                sum=sum-(d.ad*2+d.ac-d2.ad*2);
                vis[d.aid]=1;
            }    
            else
            {
                sum=sum-c2.bc;
                vis[c2.bid]=1;
                qd.push(d);qc.push(c);
            }    
        }
        else
        {
            if(d.ad*2+d.ac-d2.ad*2<c.bc)
            {
                sum=sum-(d.ad*2+d.ac-d2.ad*2);
                vis[d.aid]=1;
                qc.push(c);
            }    
            else
            {
                sum=sum-c.bc;
                vis[c.bid]=1;
                qd.push(d);
            }
        }
        ans[n-i]=sum;
    }
    for(ll i=1;i<=n;i++)
        printf("%lld\n",ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/NSD-email0820/p/9692685.html