Luogu P1315 观光公交 题解报告
【题目大意】
有$n$个公交站和$m$个乘客,从第$i$个站到第$i+1$个站所需时间为$t_i$,第$i$个乘客将在时间$c_i$到达$a_i$站,在$b_i$站下车。现在有$k$个加速器,如果在$i\to i+1$路段使用加速器,可以使得$t_i-1$,但要保证$t_i>0$,求所有乘客的旅行时间之和最小为多少?(每个乘客的旅行时间定义为下车的时间减去到达车站的时间)
【思路分析】
emmmm其实一开始没想到贪心的,我一开始还以为这会是一道DP题?(bushi)
好吧这题的贪心策略确实有些难想,就是每次用加速器的时候要保证这个加速器可以是最多的乘客旅行时间减少。
那么我们如何实现呢?
先定义几个变量:
$T[i]$表示公交车到达第$i$站的时间点,$dn[i]$记录在第$i$站下车的人数,$sum$数组记录$dn$数组的前缀和,$lst[i]$表示第$i$站最晚到达的乘客到达的时间点,$bft[i]$表示如果在$i\to i+1$路段使用加速器,旅行时间减少的乘客最后下车的站点。
然后我们明确几个转移关系:
$T[i]=max(T[i-1],lst[i-1])+t[i]$
$if(T[i+1]>lst[i+1])\ bft[i]=bft[i+1]$
$else\ bft[i]=i+1$
对于每个加速器,我们找到一个路段使用后使得旅行时间减少的乘客最多,然后改变相应变量,再重复操作,复杂度为$O(nk)$
【代码实现】
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #define g() getchar() 8 #define rg register 9 #define go(i,a,b) for(rg int i=a;i<=b;i++) 10 #define back(i,a,b) for(rg int i=a;i>=b;i--) 11 #define db double 12 #define ll long long 13 #define il inline 14 #define pf printf 15 #define mem(a,b) memset(a,b,sizeof(a)) 16 using namespace std; 17 int fr(){ 18 int w=0,q=1; 19 char ch=g(); 20 while(ch<'0'||ch>'9'){ 21 if(ch=='-') q=-1; 22 ch=g(); 23 } 24 while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=g(); 25 return w*q; 26 } 27 const int N=1002,M=10002; 28 const int INF=1e9+7; 29 int n,m,k,ans; 30 int t[N],dn[N],lst[N],T[N],sum[N],bft[N]; 31 struct pas{ 32 int c,a,b; 33 }p[M]; 34 int main(){ 35 //freopen("","r",stdin); 36 //freopen("","w",stdout); 37 n=fr();m=fr();k=fr(); 38 go(i,1,n-1) t[i]=fr(); 39 go(i,1,m){ 40 p[i]=(pas){fr(),fr(),fr()}; 41 dn[p[i].b]++; 42 lst[p[i].a]=max(lst[p[i].a],p[i].c); 43 } 44 go(i,2,n) T[i]=max(T[i-1],lst[i-1])+t[i-1]; 45 go(i,1,n) sum[i]=sum[i-1]+dn[i]; 46 go(i,1,m) ans+=T[p[i].b]-p[i].c; 47 lst[n]=INF; 48 while(k--){ 49 rg int mx=0,id=0; 50 back(i,n-1,1) 51 if(T[i+1]>lst[i+1]) bft[i]=bft[i+1]; 52 else bft[i]=i+1; 53 go(i,1,n-1) 54 if(sum[bft[i]]-sum[i]>mx&&t[i]) mx=sum[bft[i]]-sum[i],id=i; 55 ans-=mx;t[id]--; 56 go(i,2,n) T[i]=max(T[i-1],lst[i-1])+t[i-1];//记得更新数组的值 57 } 58 pf("%d\n",ans); 59 return 0; 60 }