没想到,最终还是太弱了。自己写的没4毫秒就WA了。翻了一下别人的。发现思路完全不一样。所以我想把自己的思路说出来,和大家分享一下。也希望帮我指正。
首先对于该题。我设 S[i] 的值为所有在 i 前面的点到 i 所需的费用和。那么我写出来的状态转移方程便是 f[i] = min(f[i], f[j] + tot[i] - tot[j+1] * (j - i))+a[i] (j <= i )
最终得出的不等式就是(设j比k优,且k < j) f[j] + (t[j+1]*i) - f[k] - (t[k+1]*k) <= (t[j+1]-t[k+1])*i
然而WA了。那么正解就是差分维护前缀和了。(这不是重点,重点是我错哪了?)
1 #include<cstdio> 2 #include<iostream> 3 #define rep(i,j,k) for(register int i = j; i <= k; i++) 4 #define ll long long 5 #define maxn 1002333 6 using namespace std; 7 8 inline int read() { 9 int s = 0, t = 1; char c = getchar(); 10 while( !isdigit(c) ) { if( c == '-' ) t = -1; c = getchar(); } 11 while( isdigit(c) ) s = s * 10 + c - 48, c = getchar(); 12 return s * t; 13 } 14 15 ll f[maxn], y[maxn], ts[maxn], s[maxn]; 16 int q[maxn]; 17 18 int main() { 19 //freopen("in.txt","r",stdin); 20 int n = read(), x; 21 rep(i,1,n) f[i] = read(); 22 ts[0] = s[0] = 0; rep(i,1,n) { s[i] = (x = read()) + s[i-1]; ts[i] = y[i] = 1ll * i * x + y[i-1]; } 23 //rep(i,1,n) cout<<ts[i]<<" "; cout<<endl; 24 //rep(i,1,n) 25 int l = 0, r = 0; q[0] = 0; 26 rep(i,1,n){ 27 //cout<<"WORK "<<i<<endl; 28 //rep(j,l,r) cout<<q[j]<<" "; cout<<endl; 29 while( l < r && y[q[l+1]]-y[q[l]] <= (s[q[l+1]]-s[q[l]]) * i ) l++; 30 //rep(j,l,r) cout<<q[j]<<" "; cout<<endl; 31 f[i] += f[q[l]] + (s[i]-s[q[l]])*i - ts[i] + ts[q[l]]; y[i] += f[i]; 32 //cout<<f[i]<<" "<<y[i]<<endl; 33 while( l < r && (y[q[r]]-y[q[r-1]])*(s[i]-s[q[r]]) >= (y[i]-y[q[r]])*(s[q[r]]-s[q[r-1]]) ) r--; 34 q[++r] = i; 35 //rep(j,l,r) cout<<q[j]<<" "; cout<<endl; 36 } 37 cout<<f[n]<<endl; 38 return 0; 39 }