• 【水题】NOIP201504推销员


    NOIP201504推销员

    【问题描述】  

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

    【输入格式】  

    第一行有一个正整数 N,表示街住户数量,接下来一行有 N 个正整数,其中第 i 个整数 Si 表示第 i 家住户到入口距离保证 S1<=S2<=S3....<10 的 8 次方。接下来一行有 N 个整数,其中第 i 个整数 Ai 表示向第 i 个住户推销产品会积累疲劳值。保证 Ai<=10 的 3 次方。

    【输出格式】  

    输出 N 行,每行一个正整数,其中第 i 行整数表示当 x=i,阿明积累的疲劳值。

    【输入样例】    

    5
    1 2 3 4 5
    1 2 3 4 5
    

    【输出样例】

    15
    19
    22
    24
    25
    

    【数据规模与约定】

    数据范围:1<= N <= 100000。

    【试题分析】

         不会做?会暴力吗?普通来说60分做法,100分其实一点也没问题!设一个结构体每次按优先级排序就可以了,想不到学校OJ都有那么多人抄的集训队爷的代码……

        NOIP的数据水,在洛谷等oj上过了官方样例,但是没有过老师加上的样例……

        不过放心,这是改了在学校OJ上AC的代码……

        并木有线段树等等高深算法……

        暴力搞定一切……

    【代码】

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm> 
    using namespace std;
    inline long long read()
    {
    	long long x=0,f=1;char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*f;
    }
    struct data
    {
    	long long num;//num为推销第i家推销花费的精力
    	long long k;//k为第i家距镇口的距离
    	long long f;//f为只对第i家进行推销的花费经历
    }a[100001];
    bool cmp(data a,data b)
    {
    	return a.k<b.k;
    }
    bool cmp1(data a,data b)
    {
    	return a.f>b.f;
    }
    bool cmp2(data a,data b)
    {
    	return a.num>b.num;
    } 
    long long n,trueto[100001];//true数组记录是否选择过,其实完全可以不要
    int main()
    {
        n=read();
        for(long long i=1;i<=n;i++) a[i].k=read();
        for(long long i=1;i<=n;i++) a[i].num=read();
        sort(a+1,a+n+1,cmp);//先按距村口远近排序
        long long sum=0;
        for(long long i=1;i<=n;i++) a[i].f=(a[i].k*2)+a[i].num;//计算f
        sort(a+1,a+n+1,cmp1);//对f进行排序
        long long ans=a[1].f;//第一个要最大一定要选单独推销精力最大的一家
        long long temp=a[1].k,tmp2,temp2=a[1].num;//记录,方便后面查找
        cout<<ans<<endl;//第一个输出
        sort(a+1,a+n+1,cmp2);//按num排序,因为当选择了这家以后比它距村口近的只需要加上推销的经历
    	for(int i=1;i<=n;i++) if(a[i].k==temp&&ans==a[i].f&&temp2==a[i].num) {trueto[i]=1;tmp2=i;break;}//记录我们原先找到f的地方进行标记 
        for(long long i=1;i<=n;i++)
        {
    	    if(trueto[i]) continue;//其实只有上面的f跳过
        	long long maxn=a[i].num;
        	long long tmp=i;
    		trueto[tmp]=1;
    		if(a[tmp].k<=temp)ans+=a[tmp].num;//如果距村口比最大的距离短那么只需要加上这个精力
    		else ans-=(a[tmp2].k*2),tmp2=tmp,temp=a[tmp].k,ans+=a[tmp].f;//要去掉原先最大的的路程计算,然后要加上这一次的
    		printf("%lld
    ",ans);//输出
        }
    }
  • 相关阅读:
    时装画基础知识--如何画人体
    马士兵java视频学习顺序
    Mysql 中文字符乱码问题
    zendstudio 设置默认编码 utf-8 gbk
    MYSQL 本地无ROOT权限 忘记密码
    windows 3389 远程
    windows 老掉牙CMD的命令
    mysql-常用注入渗透手法
    ubuntu 添加多个IP
    windows下简单配置apache
  • 原文地址:https://www.cnblogs.com/wxjor/p/5910787.html
Copyright © 2020-2023  润新知