设这几个东西:
- \(t[i]\),最晚到达 \(i\) 站的人到达的时间;
- \(arrive[i]\),车到达 \(i\) 站的时间,显然 \(arrive[i]=max(arrive[i-1],t[i-1])+D[i-1]\)。
所以要求的答案就是:\(\sum arrive[target[i]]-reach[i]\),\(reach[i]\)为\(i\)到站的时间
当我们考虑到加速器的时候,对于一个站,当 \(arrive[i]<=t[i]\) 时,前面不管用了多少个加速器都不会影响到后面的时间,所以我们再设这样一个东西:\(f[i]\)为,在 \(i\) 这个站用了加速器后能够影响到的 \(i\) 后面最远的站,当 \(arrive[i]<=t[i]\) 时,\(f[i]=i+1\),否则,\(f[i]=f[i+1]\)。所以我们在 \(i\) 站用一个加速器,就会使得答案减少 \(S[f[i]]-S[i]\) ,其中,\(S[i]\)为在 \(i\) 站下车的人数的前缀和,所以我们只需要每次在一个使得 \(S[f[i]]-S[i]\) 最大的 \(i\) 上放一个加速器并实时更新一下 \(arrive[i]\) 和 \(f[i]\) 就好了
//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define N (1010)
#define RG register
using namespace std;
inline int gi(){ RG int x=0,q=1; RG char ch=getchar(); while( ( ch<'0' || ch>'9' ) && ch!='-' ) ch=getchar();
if( ch=='-' ) q=-1,ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; }
int n,m,k,D[N],ret;
int t[N],arrive[N],S[N],f[N];
void init(){
n=gi(),m=gi(),k=gi();
for(RG int i=1;i<n;i++) D[i]=gi();
for(RG int i=1;i<=m;i++){
int reach=gi(),outset=gi(),target=gi();
ret-=reach;
t[outset]=max(t[outset],reach);
S[target]++;
}
for(RG int i=1;i<=n;i++)
arrive[i]=max(arrive[i-1],t[i-1])+D[i-1];
for(RG int i=1;i<=n;i++) S[i]+=S[i-1];
}
void work(){
while(k){
f[n]=f[n-1]=n;
for(RG int i=n-2;i;i--)
if(arrive[i+1]<=t[i+1]) f[i]=i+1;
else f[i]=f[i+1];
int Max=0,s;
for(RG int i=1;i<n;i++)
if(S[f[i]]-S[i]>Max&&D[i])
Max=S[f[i]]-S[i],s=i;
if(!Max) break; D[s]--; k--;
for(RG int i=1;i<=n;i++)
arrive[i]=max(arrive[i-1],t[i-1])+D[i-1];
}
for(RG int i=1;i<=n;i++) ret+=arrive[i]*(S[i]-S[i-1]);
printf("%d\n",ret);
}
int main(){ init(); work(); return 0; }