传送门:bzoj2726
斜率优化。
按照“费用提前计算”的规则将每个任务的 S S S花费提前处理,列出 d p dp dp转移:
d p i = d p j − ( S + T i ) C j + T i C i + S C n dp_i=dp_j-(S+T_i)C_j+T_iC_i+SC_n dpi=dpj−(S+Ti)Cj+TiCi+SCn
其中 C i = ∑ j = 1 i F j , T i = ∑ j = 1 i T j C_i=\sum\limits_{j=1}^iF_j,T_i=\sum\limits_{j=1}^iT_j Ci=j=1∑iFj,Ti=j=1∑iTj
转成斜率的形式:
F j = ( S + T i ) C j − T i C i − S C n + F i F_j=(S+T_i)C_j-T_iC_i-SC_n+F_i Fj=(S+Ti)Cj−TiCi−SCn+Fi
因为 C j C_j Cj是单调的,其实可以在凸包上二分,cdq分治也可以做。
#include
using namespace std;
const int N=3e5+100;
typedef long long ll;
typedef double db;
int n,S,top,stk[N];
int c[N],t[N];ll f[N];
struct P{
int x;ll y;int k;ll b;int id;
bool operator<(const P&ky)const{
return k
inline void rd(yyy &x)
{
cp=getchar();int pr=0;x=0;
for(;!isdigit(cp);cp=getchar()) if(cp=='-') pr=1;
for(;isdigit(cp);cp=getchar()) x=(x<<3)+(x<<1)+(cp^48);
if(pr) x=-x;
}
inline db slp(int A,int B)
{
if(p[A].x==p[B].x) return (p[B].y>=p[A].y)?(1e18):(-1e18);
return (p[B].y-p[A].y)/(db)(p[B].x-p[A].x);
}
void sol(int l,int r)
{
if(l==r) {p[l].y=f[l];return;}
int mid=(l+r)>>1,k,i=l,j=mid+1;
for(k=l;k<=r;++k)
if(p[k].id<=mid) rep[i++]=p[k];
else rep[j++]=p[k];
for(k=l;k<=r;++k) p[k]=rep[k];
sol(l,mid);
top=0;
for(k=l;k<=mid;++k){
for(;top>1 && slp(stk[top-1],stk[top])>=slp(stk[top],k);--top);
stk[++top]=k;
}
for(k=mid+1,i=1;k<=r;++k){
for(;ir) || (i<=mid && p[i].x