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 }