目录:
题目:
分析:
首先按照费用提前计算的思想,最后可以得到状态转移方程
f[i]=min{f[j]+sumt[i]∗(sumc[i]−sumc[j])+S∗(sumc[n]−sumc[j])}
f
[
i
]
=
m
i
n
{
f
[
j
]
+
s
u
m
t
[
i
]
∗
(
s
u
m
c
[
i
]
−
s
u
m
c
[
j
]
)
+
S
∗
(
s
u
m
c
[
n
]
−
s
u
m
c
[
j
]
)
}
O(n2)
O
(
n
2
)
把仅与
i
i
有关的单独提取出来可以得到
把有关
j
j
的值看作变量其它当作常量得到
可以发现这是斜率优化,在本题维护的是下凸壳,所以可以用单调队列解决(斜率满足单调性)
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#define LL long long
#define h happy
#define XJQ 1000000007
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int f[10001],q[20001];
int summ[10001],sumt[10001];
int m,t;
int main()
{
int n=read(),s=read();
for(int i=1;i<=n;i++)
{
t=read();m=read();
sumt[i]=sumt[i-1]+t;
summ[i]=summ[i-1]+m;
}
int l=1,r=1;
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int i=1;i<=n;i++)
{
while(l<r&&f[q[l+1]]-f[q[l]]<=(s+sumt[i])*(summ[q[l+1]]-summ[q[l]])) l++;
f[i]=f[q[l]]-(s+sumt[i])*summ[q[l]]+sumt[i]*summ[i]+s*summ[n];
while(l<r&&(f[q[r]]-f[q[r-1]])*(summ[i]-summ[q[r]])>=(f[i]-f[q[r]])*(summ[q[r]]-summ[q[r-1]]))
r--;
q[++r]=i;
}
cout<<f[n];
return 0;
}