bzoj 3156: 防御准备

这个题2333,有一个情况就是从一个点i一直山底的,直接计算出答案,一个是到山顶的,用斜率优化来算,最后答案是两个加起来(可能会说反)

最后,本蒟蒻来BB一下对斜率优化的理解吧。

其实就是无脑的写一个f[i]从f[j]转移来的式子,在搞一个j,k一个大,一个小,用小(大)于号连起来,变一下形,让左边存在未知数(j,k)右边是关于i的式子

有了式子之后,(因为我太弱,只能随便理解,如有错误,希望大神指出),如果是小于号,肯定是左边越小越优,(小于号就小,很有道理吧,,其实本蒟蒻是假设一些值不变,然后要使左边变小,需要变那些值,类似于物理分析),然后,大于号反过来呗。

 1 #include <bits/stdc++.h>
 2 #define LL  long long
 3 #define lowbit(x) x&(-x)
 4 #define inf 0x3f3f3f3f
 5 #define eps 1e-5
 6 #define N 1000005
 7 using namespace std;
 8 inline LL ra()
 9 {
10     LL x=0,f=1; char ch=getchar();
11     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
12     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
13     return x*f;
14 }
15 LL f[N],ans=(1LL<<60);
16 LL cst[N],q[N];
17 LL n;
18 LL slope(LL j, LL k)
19 {
20     return (2*f[j]+j*j-2*f[k]-k*k);
21 }
22 int main()
23 {
24     n=ra();
25     for (LL i=1; i<=n; i++) cst[n-i+1]=ra();
26     f[1]=cst[1];
27     LL l=1,r=1; q[1]=1;
28     ans=min(ans,f[1]+n*(n-1)/2);
29     for (LL i=2; i<=n; i++)
30     {
31         while (l<r && slope(q[l+1],q[l])<=(i*2-1)*(q[l+1]-q[l])) l++;
32         LL t=q[l];
33         f[i]=f[t]+(i-t-1)*(i-t)/2+cst[i];
34         ans=min(ans,f[i]+(n-i)*(n-i+1)/2);  //!!!!!!
35         while (l<r && slope(i,q[r])*(q[r]-q[r-1])<=slope(q[r],q[r-1])*(i-q[r])) r--;
36         q[++r]=i;
37     }
38     cout<<ans;
39     return 0;
40 }

 

posted @ 2017-03-13 21:03  ws_ccd  阅读(181)  评论(0编辑  收藏  举报