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);//输出 } }