bzoj 3437 小K的农场 斜率优化

   没想到,最终还是太弱了。自己写的没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 }

 

posted on 2016-03-10 18:13  83131  阅读(170)  评论(0编辑  收藏  举报

导航