bzoj 1911: [Apio2010]特别行动队
Description
Input
Output
Sample Input
4
-1 10 -20
2 2 3 4
-1 10 -20
2 2 3 4
Sample Output
9
HINT
Source
MDZZ又是一道类似玩具装箱的划分型DP。。。
单调性的话 貌似 f[i]=min/max(f[j]+w[i,j])的转移都有单调性。。。
所以拿来练二分栈的板子了。。。
和n^2对拍没有问题就交了。。。
1000000一开始吓死我了,然而过了。。。
1 // MADE BY QT666 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 #include<queue> 7 #include<set> 8 #include<cstdlib> 9 #include<cstring> 10 #include<string> 11 #include<ctime> 12 #define lson num<<1 13 #define rson num<<1|1 14 #define int long long 15 using namespace std; 16 typedef long long ll; 17 const int N=1000050; 18 int gi() 19 { 20 int x=0,flag=1; 21 char ch=getchar(); 22 while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();} 23 while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); 24 return x*flag; 25 } 26 int a,b,c,n; 27 int s[N],f[N]; 28 struct data{int l,r,p;}q[N]; 29 int work(int x){ 30 return a*x*x+b*x+c; 31 } 32 int cal(int j,int i){ 33 return f[j]+work(s[i]-s[j]); 34 } 35 int find(data t,int x) 36 { 37 int l=t.l,r=t.r; 38 while(l<=r){ 39 int mid=(l+r)>>1; 40 if(cal(t.p,mid)>cal(x,mid)) 41 l=mid+1; 42 else r=mid-1; 43 } 44 return l; 45 } 46 main() 47 48 n=gi(); 49 a=gi(),b=gi(),c=gi(); 50 for(int i=1;i<=n;i++) s[i]=gi(),s[i]+=s[i-1]; 51 int head=1,tail=0; 52 q[++tail]=(data){0,n,0}; 53 for(int i=1;i<=n;i++){ 54 if(head<=tail&&i>q[head].r)head++; 55 f[i]=cal(q[head].p,i); 56 if(head>tail||cal(i,n)>=cal(q[tail].p,n)){ 57 while(head<=tail&&cal(i,q[tail].l)>=cal(q[tail].p,q[tail].l)) 58 tail--; 59 if(head>tail) 60 q[++tail]=(data){i,n,i}; 61 else{ 62 int t=find(q[tail],i); 63 q[tail].r=t-1; 64 q[++tail]=(data){t,n,i}; 65 } 66 } 67 } 68 printf("%lld\n",f[n]); 69 }