这是我赛时写的玄学代码,当时测完大样例直接下一题了。
当时思路是:找出所有 连续的 不下降的 子序列,然后 这一段的油 全在 这一段的第一个站点 加掉。
就比如油价是 1 2 3 2 3,按照我的想法,就会把前 3 个站点的油在第 1 个站加满,后 2 个站点的油 在第 4 个站加满。按照最优想法,不是应该全在第 1 个站点加吗?
总之修修改改,缝缝补补,最后居然过了 CCF 的数据,拿了 100pts。
求 hack 或证明这种奇怪算法的正确性?
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
int n;
ll d,v[100005],a[100005];
ll sum[100005];
int main(){
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
scanf("%d%lld",&n,&d);
for(int i=1;i<n;++i) scanf("%lld",&v[i]);
for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
for(int i=2;i<=n;++i) sum[i]=sum[i-1]+v[i-1];
ll tot=(sum[n]+d-1)/d;
ll ans=0,rem=0;
for(int i=1,j=1;i<n;++i){
// cout<<i<<' '<<sum[i]<<endl;
while(j<n&&a[i]<=a[j]) j++;
ll x=sum[j]-sum[i];
if((x+d-1)/d!=(x-rem+d-1)){
x-=rem;
rem=0;
}
ans+=a[i]*((x+d-1)/d);
rem+=(x+d-1)/d*d-x;
// printf("%d->%d: %lld L, %lld km, rem %lld km, %lld RMB\n",i,j,(x+d-1)/d,x,rem,ans);
i=j-1;
}
printf("%lld\n",ans);
return 0;
}