3156: 防御准备

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 2811  Solved: 1178
[Submit][Status][Discuss]

Description

 

Input

第一行为一个整数N表示战线的总长度。

第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。

 

Output

共一个整数,表示最小的战线花费值。

 

Sample Input



10
2 3 1 5 4 5 6 3 1 2

Sample Output


18

HINT

 



1<=N<=10^6,1<=Ai<=10^9

 

Source

Katharon+#1

将a[i]反过来,因为最后一个检查点一定要放置守卫塔,反过来就变成第一个放置守卫塔

斜率优化,少写个LL WA了半天

f[i]=min{f[j]+a[i]+s[i-1]-s[j]-(i-j-1)*j}

[frac{f[j]-f[k]+s[k]-s[j]+j^{2}-k^{2}+j-k}{j-k}<i]

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 #define LL long long
 6 const int MAXN=1000005;
 7 
 8 int n,l,r;
 9 int a[MAXN],q[MAXN];
10 LL ans=(1LL<<60),f[MAXN],s[MAXN];
11 
12 double slope(LL k,LL j)
13 {
14     return (double)(f[j]-f[k]+s[k]-s[j]+j*j-k*k+j-k)/(j-k);
15 }
16 
17 int main()
18 {
19     scanf("%d",&n);
20     for(int i=n;i;i--)
21         scanf("%d",&a[i]);
22     for(int i=1;i<=n;i++)
23         s[i]=s[i-1]+i;
24     f[1]=a[1];q[1]=1;l=r=1;
25     ans=min(ans,f[1]+s[n]-s[1]-n+1);
26     for(int i=2;i<=n;i++)
27     {
28         while(l<r&&slope(q[l],q[l+1])<i) l++;
29         int t=q[l];
30         f[i]=f[t]+a[i]+s[i-1]-s[t]-(LL)(i-t-1)*t;
31         ans=min(ans,f[i]+s[n]-s[i]-(LL)(n-i)*i);
32         while(l<r&&slope(q[r],i)<slope(q[r-1],q[r])) r--;
33         q[++r]=i;
34     }
35     printf("%lld",ans);
36     return 0;
37 }
原文地址:https://www.cnblogs.com/InWILL/p/9607065.html