【BZOJ】2726: [SDOI2012]任务安排-斜率优化&CDQ二分

传送门: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=1iFj,Ti=j=1iTj

转成斜率的形式:
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)CjTiCiSCn+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

你可能感兴趣的:(cdq分治,斜率优化)