zoukankan      html  css  js  c++  java
  • Codevs 5126 推销员 2015年NOIP全国联赛普及组

    5126 推销员
    时间限制: 1 s
    空间限制: 128000 KB
    题目等级 : 黄金 Gold
    题目描述 Description
    阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有N家住户,第i家住户到入口的距离为Si米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的X家住户推销产品,然后再原路走出去。阿明每走1米就会积累1点疲劳值,向第i家住户推销产品会积累Ai点疲劳值。阿明是工作狂,他想知道,对于不同的X,在不走多余的路的前提下,他最多可以积累多少点疲劳值。
    输入描述 Input Description
    第一行有一个正整数N,表示螺丝街住户的数量。
    接下来的一行有N个正整数,其中第i个整数Si表示第i家住户到入口的距离。数据保证S1≤S2≤…≤Sn<10^8。
    接下来的一行有N个正整数,其中第i个整数Ai表示向第i户住户推销产品会积累的疲劳值。数据保证Ai<10^3。
    输出描述 Output Description
    输出N行,每行一个正整数,第i行整数表示当X=i时,阿明最多积累的疲劳值。
    样例输入 Sample Input
    【样例1】
    5
    1 2 3 4 5
    1 2 3 4 5
    【样例2】
    5
    1 2 2 4 5
    5 4 3 4 1
    样例输出 Sample Output
    【样例1】
    15
    19
    22
    24
    25
    【样例2】
    12
    17
    21
    24
    27
    数据范围及提示 Data Size & Hint
    1≤N≤100000
    注:请用 scanf 输入。

    /*
    贪心n^2乱搞60. 
    */
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define MAXN 100001
    using namespace std;
    int n,m,max1,maxt,ans,tot,cut,maxd;
    //bool b[MAXN];
    struct data{int sum,w,o,x;}a[MAXN*4],b[MAXN*4];
    struct datas{int sum,w;}s[MAXN];
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    bool cmp1(const data & x,const data & y)
    {
        if(x.x!=y.x)
        return x.x>y.x;
    }
    bool cmp2(const data & x,const data & y)
    {
        if(x.sum!=y.sum)
        return x.sum>y.sum;
    }
    int main()
    {
        freopen("2015salesman.in","r",stdin);
        freopen("2015salesman.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++)
            s[i].w=read(),a[i].w=b[i].w=s[i].w,a[i].o=b[i].o=i;
        for(int i=1;i<=n;i++)
        {
            s[i].sum=2*s[i].w+read();a[i].sum=b[i].sum=s[i].sum;
            a[i].x=b[i].x=s[i].sum-2*s[i].w;
            if(s[i].sum>max1)
            {
                max1=s[i].sum;maxt=i;maxd=s[i].w;
            }
        }
        a[maxt].w=0,b[maxt].sum=0;
        printf("%d
    ",max1);
        for(int i=2;i<=n;i++)
        {
            int maxans=0,y=-1;
            sort(a+1,a+maxt,cmp1);
            int x=a[1].x;
            if(maxt!=n)
            {
                sort(b+maxt,b+n+1,cmp2);
                y=b[maxt].sum;
            }
            if(max1+x>=y+max1-s[maxt].w*2)
            {
                max1+=x;
                a[1].x=0;
            }
            else {
                b[1].sum=0;
                max1=y+max1-s[maxt].w*2;
                maxt=b[i].o;
            }
            printf("%d
    ",max1);
        }
        return 0;
    }
    /*
    n范围10^5.
    然后就想到了log.
    然后码了1个小时线段树维护orz.
    然后不会标记什么的.
    正解优先队列维护+贪心策略.
    贪心策略看数据发现第i个答案是用到i-1个的ans的.
    然后我们肯定要从前边或者后边找一个最大的更新ans.
    然后就有了n^2暴力.
    我们把问题转化成最值问题.
    贪心的话我们扩展最优位置前面的.
    然后将前面的入堆.
    有更优的我们就向后更新下最优位置.
    巧妙完成两段区间的更新. 
    */
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define MAXN 100001
    using namespace std;
    int n,m,ans;
    struct data
    {
        int x,w;
        bool operator <(data x)const {
            return w<x.w;
        }
    }s[MAXN];
    priority_queue<data>q;
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
        return x*f;
    }
    void slove()
    {
        data x;x.w=x.x=0;int now=0,max1;
        q.push(x);
        for(int i=1;i<=n;i++)
        {
            int next=now;
            x=q.top();
            max1=x.w;
            for(int j=now+1;j<=n;j++)
            {
                if(s[j].w+(s[j].x-s[now].x)*2>max1)
                {
                    max1=s[j].w+(s[j].x-s[now].x)*2;
                    next=j;
                }
            }
            s[next].w+=(s[next].x-s[now].x)*2;
            if(next!=now) q.push(s[next]);
            for(int j=now+1;j<next;j++)
              q.push(s[j]);
            now=next;
            x=q.top();
            ans+=x.w;
            q.pop();
            printf("%d
    ",ans);
        }
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
          s[i].x=read();
        for(int i=1;i<=n;i++)
          s[i].w=read();
         slove();
        return 0;   
    }
  • 相关阅读:
    阅读笔记:管理学
    Vs2010中文版MSDN 安装方法
    .NET 产品版权保护方案 (.NET源码加密保护)
    WPF 判断是否为设计(Design)状态
    重写成员时违反了继承安全性规则。重写方法的安全可访问性必须与所重写方法的安全可访问性匹配。
    没有为此解决方案配置选中要生成的项目 .
    何崚谈阿里巴巴前端性能优化最佳实践
    Oracle10GODP连接11G数据库,出现ORA 1017用户名/口令无效; 登录被拒绝 的问题
    HTTP、TCP、UDP、Socket (转)
    编译的时候生成.g.cs还有.g.i.cs,有什么区别?
  • 原文地址:https://www.cnblogs.com/nancheng58/p/6070752.html
Copyright © 2011-2022 走看看