[NOIP2011]观光公交
——!x^n+y^n=z^n
题目描述
风景迷人的小城Y 市,拥有n 个美丽的景点。由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务。观光公交车在第 0 分钟出现在 1号景点,随后依次前往 2、3 、4 ……n 号景点。从第 i 号景点开到第 i+1 号景点需要 Di 分钟。任意时刻,公交车只能往前开,或在景点处等待。
设共有m 个游客,每位游客需要乘车1 次从一个景点到达另一个景点,第i 位游客在Ti 分钟来到景点 Ai ,希望乘车前往景点Bi (Ai<Bi )。为了使所有乘客都能顺利到达目的地,公交车在每站都必须等待需要从该景点出发的所有乘客都上车后才能出发开往下一景点。
假设乘客上下车不需要时间。
一个乘客的旅行时间,等于他到达目的地的时刻减去他来到出发地的时刻。因为只有一辆观光车,有时候还要停下来等其他乘客,乘客们纷纷抱怨旅行时间太长了。于是聪明的司机ZZ给公交车安装了 k 个氮气加速器,每使用一个加速器,可以使其中一个 Di 减1 。对于同一个Di 可以重复使用加速器,但是必须保证使用后Di 大于等于0 。
那么ZZ该如何安排使用加速器,才能使所有乘客的旅行时间总和最小?
输入输出格式
输入格式:
输入文件名为bus.in。
第1 行是3 个整数n, m, k ,每两个整数之间用一个空格隔开。分别表示景点数、乘客数和氮气加速器个数。
第2 行是n-1 个整数,每两个整数之间用一个空格隔开,第i 个数表示从第i 个景点开往第i+1 个景点所需要的时间,即 Di 。
第3 行至m+2 行每行3 个整数 Ti, Ai, Bi,每两个整数之间用一个空格隔开。第 i+2 行表示第i 位乘客来到出发景点的时刻,出发的景点编号和到达的景点编号。
输出格式:
输出文件名为bus.out。共一行,包含一个整数,表示最小的总旅行时间。
输入输出样例
输入样例1#:
3 3 2
1 4
0 1 3
1 1 2
5 2 3
输出样例1#:
10
说明
【输入输出样例说明】
对D2 使用2 个加速器,从2 号景点到 3 号景点时间变为 2 分钟。
公交车在第1 分钟从1 号景点出发,第2 分钟到达2 号景点,第5 分钟从2 号景点出发,第7 分钟到达 3 号景点。
第1 个旅客旅行时间 7-0 = 7 分钟。
第2 个旅客旅行时间 2-1 = 1 分钟。
第3 个旅客旅行时间 7-5 = 2 分钟。
总时间 7+1+2 = 10分钟。
【数据范围】
对于10% 的数据,k=0 ;
对于20% 的数据,k=1 ;
对于40% 的数据,2 ≤ n ≤ 50,1 ≤ m ≤ 1,000,0 ≤ k ≤ 20,0 ≤ Di ≤ 10,0 ≤ T i ≤ 500;
对于60% 的数据,1 ≤ n ≤ 100,1 ≤ m ≤ 1,000,0 ≤ k ≤ 100 ,0 ≤ Di ≤ 100,0 ≤ T i ≤ 10,000 ;
对于100%的数据,1 ≤ n ≤ 1,000,1 ≤ m ≤ 10,000 ,0 ≤ k ≤ 100,000,0 ≤ Di ≤ 100 ,0 ≤ T i ≤ 100,000。
noip2011提高组day2第3题
随你们怎么评价把,反正蒟蒻我觉得很难,再加上我本身就是greedy蒟蒻啊啊啊...有点想哭。
考虑某一个点i的到站时间,正常来说是上一个站的到站时间加上两站间的时间,但有可能一些无聊的乘客很晚才到...应该是两个间取最大值。TAT
即:time[i]=Max{time[i-1],last[i-1]}+d[i-1]
所以我们记录time[i]代表到达i的时间,last[i]表示最晚到i的乘客的时间,那么对答案的贡献就为time[目的地]-初始等的时间。
注意初始的时间是不会变的,所以我们要尽可能的减小time,而修改这个我们只能通过修改d,每次修改d都会有一些乘客受到影响,假设在i改变d会影响到f[i]后的乘客,那我们利用前缀和s,记录但前位置及之前就下车的乘客,那么会被影响到的乘客就为s[i+f[i]]-s[i],显然这个量也不会变,可以预处理出来。然后每次都选择s[i+f[i]]-s[i]最大的去更新,因为你用氮气加速互不影响呵呵(所以要贪心,Lowbee我眼泪都快掉出来了...)。
然后你暴力枚举找最大就行了,根本不会超时,想不到把。
唉,反正觉得不会想到这种方法的我很绝望,连暴力一点骗分的程序都不会,%%%大佬。
代码:
1 //2017.10.30 2 //greedy 3 #include<iostream> 4 #include<cstdio> 5 #include<cstring> 6 using namespace std; 7 typedef long long ll ; 8 inline int read(); 9 int Max(int x,int y){return x>y?x:y;} 10 namespace lys{ 11 const int N = 1e3 + 7 ; 12 int d[N],s[N],last[N],time[N],f[N],rc[N]; 13 int n,m,k,M,pos; 14 ll ans,tot; 15 int main(){ 16 int i,j,x,y; 17 n=read(); m=read(); k=read(); 18 for(i=1;i<n;i++) d[i]=read(); 19 for(i=1;i<=m;i++){ 20 x=read(); y=read(); rc[i]=read(); 21 if(last[y]<x) last[y]=x; 22 for(j=rc[i];j<=n;j++) s[j]++; 23 tot+=x; 24 } 25 while(k--){ 26 for(i=2;i<=n;i++) time[i]=Max(time[i-1],last[i-1])+d[i-1]; 27 f[n]=0; 28 for(i=n-1;i;i--) 29 if(time[i+1]>last[i+1]) f[i]=f[i+1]+1; 30 else f[i]=1; 31 M=-1; 32 for(i=1;i<n;i++) 33 if(d[i]&&f[i]&&(s[f[i]+i]-s[i]>M)){ 34 M=s[f[i]+i]-s[i]; 35 pos=i; 36 } 37 if(~M) d[pos]--; 38 } 39 for(i=2;i<=n;i++) time[i]=Max(time[i-1],last[i-1])+d[i-1]; 40 for(i=1;i<=m;i++) ans+=time[rc[i]]; 41 printf("%lld ",ans-tot); 42 return 0; 43 } 44 } 45 int main(){ 46 lys::main(); 47 return 0; 48 } 49 inline int read(){ 50 int kk=0,ff=1; 51 char c=getchar(); 52 while(c<'0'||c>'9'){ 53 if(c=='-') ff=-1; 54 c=getchar(); 55 } 56 while(c>='0'&&c<='9') kk=kk*10+c-'0',c=getchar(); 57 return kk*ff; 58 }