//今天有点晚了,先放几道例题
这张凸包的图可以方便感性理解斜率优化排点的原理:
(只有边缘的点有用)
EXAMPLES
(虽然说都比较水,但是相对难度还是有一些梯度。。)
1
[HNOI2008]玩具装箱TOY
#include<bits/stdc++.h>
using namespace std;
#define db double
#define int long long
const int maxn=5e4+10;
int n,L;
db s[maxn],f[maxn];
int head,tail,q[maxn];
inline db a(int i){return s[i]+i;}
inline db b(int j){return s[j]+j+L+1;}
inline db X(int j){return b(j);}
inline db Y(int j){return f[j]+b(j)*b(j);}
inline db slope(int i,int j){return (Y(i)-Y(j))/(X(i)-X(j));}
signed main(){
scanf("%lld%lld",&n,&L);
for(int i=1;i<=n;++i){
scanf("%lf",&s[i]);
s[i]+=s[i-1];
}
head=1;tail=1;
for(int i=1;i<=n;++i){
while(head<tail&&slope(q[head],q[head+1])<2*a(i))++head;
//f[i]=Y(q[head])-2*a(i)*X(q[head])+a(i)*a(i);Îó²î½Ï´ó
int j=q[head];
f[i]=f[j]+(a(i)-b(j))*(a(i)-b(j));
while(head<tail&&slope(q[tail-1],i)<slope(q[tail-1],q[tail]))--tail;
q[++tail]=i;
}
printf("%lld",(long long)f[n]);
return 0;
}
2
HDU3507打印文章
#include<bits/stdc++.h>
#define pf printf
#define sf scanf
#define ll long long
using namespace std;
const int maxn=5e5+10;
ll f[maxn],s[maxn],n,m;
inline ll y(int a,int b){return f[a]+s[a]*s[a]-f[b]-s[b]*s[b];}
inline ll x(int a,int b){return s[a]-s[b];}
int q[maxn],head,tail=0;
/*
f[i]=f[j]+(s[i]-s[j])^2+m
f[j]+s[j]^2=2*s[i] *s[j] - s[i]^2 -m + f[i];
*/
signed main (){
while(~sf("%d%d",&n,&m)){
for(int i=1;i<=n;++i)sf("%lld",&s[i]),s[i]+=s[i-1];
head=tail=1;q[head]=0;f[0]=0;
for(int i=1;i<=n;++i){
while(head<tail&&y(q[head+1],q[head])<=2*s[i]*x(q[head+1],q[head]))++head;
int j=q[head];
f[i]=f[j]+(s[i]-s[j])*(s[i]-s[j])+m;
while(head<tail&&y(q[tail],q[tail-1])*x(i,q[tail])>=y(i,q[tail])*x(q[tail],q[tail-1]))--tail;
q[++tail]=i;
}
cout<<f[n]<<"\n";
}
return 0;
}
3
[zjoi2007]仓库建设
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define sf scanf
#define pf printf
#define db double
#define re register
#define gc getchar()
#define in rd()
inline int rd(){
int num=0;char c=gc;
for(;!isdigit(c);c=gc);
for(;isdigit(c);c=gc)num=(num<<1)+(num<<3)+(c^48);
return num;
}
const int maxn=1e6+10;
//Ws[i]= w[i]*s[i] (1-i)
//s[i]--(1-i) w[i]--(1-i)
int w[maxn],s[maxn],Ws[maxn],n,c[maxn],f[maxn];
int head,tail,q[maxn];
/*
f[i]=p[j]+s[i]*(w[i]-w[j])-(Ws[i]-Ws[j])
p[j]+Ws[j]=s[i]*w[j]+f[i]+Ws[i]-s[i]*w[i]
*/
inline db slope(int a,int b){return (f[a]+Ws[a]-f[b]-Ws[b])*1.00/(w[a]-w[b])*1.00;}
signed main(){
n=in;
for(int re i=1;i<=n;++i){
s[i]=in;w[i]=in;c[i]=in;
Ws[i]+=Ws[i-1]+w[i]*s[i],w[i]+=w[i-1];
}
head=tail=1;
for(int re i=1;i<=n;++i){
while(head<tail&&slope(q[head+1],q[head])<=s[i]*1.00)++head;
int j=q[head];
f[i]=f[j]+s[i]*(w[i]-w[j])-(Ws[i]-Ws[j])+c[i];
while(head<tail&&slope(q[tail-1],q[tail])>=slope(i,q[tail]))--tail;
q[++tail]=i;
}
cout<<f[n];
return 0;
}
4
[Apio2010]特别行动队
#include<bits/stdc++.h>
#define pf printf
#define sf scanf
#define re register
#define ll long long
#define gc getchar()
#define db double
#define in rd()
using namespace std;
const int maxn=1e6+10;
inline ll rd(){
int num=0,f=1;char c=gc;
for(;!isdigit(c);c=gc)if(c=='-')f=-1;
for(;isdigit(c);c=gc)num=(num<<1)+(num<<3)+(c^48);
return num*f;
}
ll s[maxn],a,b,c,f[maxn],n;
int q[maxn],head,tail;
inline db slope(int x,int y){return (f[x]+a*s[x]*s[x]-f[y]-a*s[y]*s[y])*1.00/(s[x]-s[y])*1.00;}
/*
f[i]=a*(s[i]-s[j])*(s[i]-s[j])+b*(s[i]-s[j])+c+f[j]
f[j]+a*s[j]*s[j]=(2*a*s[i]+b)*s[j]-b*s[i]-a*s[i]*s[i]-c+f[i]
*/
signed main (){
n=in;a=in,b=in,c=in;
for(int re i=1;i<=n;++i)s[i]=in,s[i]+=s[i-1];
head=tail=0;
for(int re i=1;i<=n;++i){
while(head<tail&&slope(q[head],q[head+1])>=(2.00*a*s[i]+b*1.00))++head;
int j=q[head];
f[i]=a*(s[i]-s[j])*(s[i]-s[j])+b*(s[i]-s[j])+c+f[j];
while(head<tail&&slope(q[tail],q[tail-1])<=slope(q[tail],i))--tail;
q[++tail]=i;
}
cout<<f[n];
return 0;
}
5
[SDOI2012]任务安排
#include<bits/stdc++.h>
#define pf printf
#define sf scanf
#define ll long long
#define int long long
using namespace std;
const int maxn=3e5+10;
ll f[maxn];
int s[maxn],t[maxn],S,n;
int head,tail,q[maxn];
/*
f[j]=(t[i]+S)*s[j]-S*s[n]-s[i]*t[i]+f[i];
f[i]=f[j]+(s[i]-s[j])*t[i]+ S*(s[n]-s[j])
t[i]+S ²»µ¥µ÷£¬ËùÒÔ¶þ·Ö
*/
inline int find(int k){
if(head==tail)return q[head];
int l=head,r=tail;
while(l<r){
int mid=(l+r)>>1;
if((f[q[mid+1]]-f[q[mid]])<=k*(s[q[mid+1]]-s[q[mid]]))l=mid+1;
else r=mid;
}
return q[l];
}
signed main (){
sf("%lld%lld",&n,&S);
for(int i=1;i<=n;++i)sf("%lld%lld",&t[i],&s[i]),t[i]+=t[i-1],s[i]+=s[i-1];
head=tail=1;
f[0]=0;s[0]=0;
for(int i=1;i<=n;++i){
int j=find(t[i]+S);
f[i]=f[j]+1ll*(s[i]-s[j])*t[i]+1ll*S*(s[n]-s[j]);
while(head<tail&&(f[q[tail]]-f[q[tail-1]])*(s[i]-s[q[tail]])>=(f[i]-f[q[tail]])*(s[q[tail]]-s[q[tail-1]]))--tail;
q[++tail]=i;
}
cout<<f[n];
return 0;
}
6
Cats Transport
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=1e5+10;
int dp[maxn][150],s[maxn],a[maxn];
int h[maxn];
int n,m,P;
int q[maxn];
inline int Y(int i,int k){
return dp[i][k-1]+s[i];
}
signed main(){
scanf("%d%d%d",&n,&m,&P);
for(int i=2;i<=n;++i)scanf("%d",&h[i]),h[i]+=h[i-1];
for(int i=1;i<=m;++i){
int x,y;scanf("%d%d",&x,&y);
a[i]=y-h[x];
}
sort(a+1,a+m+1);
for(int i=1;i<=m;++i)s[i]=s[i-1]+a[i];
memset(dp,0x5f,sizeof dp);
dp[0][0]=0;
for(int k=1;k<=P;++k){
int head=1,tail=1;
for(int i=1;i<=m;++i){
while(head<tail&&(Y(q[head+1],k)-Y(q[head],k))<=(q[head+1]-q[head])*a[i])++head;
int j=q[head];
dp[i][k]=dp[j][k-1]+(i-j)*a[i]-s[i]+s[j];
// cerr<<j<<endl;
// cerr<<i<<" "<<k<<" "<<dp[i][k]<<endl;
while(head<tail&&(Y(q[tail-1],k)-Y(q[tail],k))*(q[tail-1]-i)>=(Y(q[tail-1],k)-Y(i,k))*(q[tail-1]-q[tail]))--tail;
q[++tail]=i;
}
}
printf("%lld",dp[m][P]);
return 0;
}