天天看點

【bzoj2726】[SDOI2012]任務安排 【cdq分治+斜率優化】

題目傳送門

這題和bzoj1492Cash幾乎一樣,是以這裡隻貼公式。

f[i]=min(f[j]+c[j]∗(t[i]−t[j]+s)) f [ i ] = m i n ( f [ j ] + c [ j ] ∗ ( t [ i ] − t [ j ] + s ) )

=> f[k]+c[k]∗t[i]−c[k]∗(t[k]−s)<=f[j]+c[j]∗t[i]−c[j]∗(t[j]−s) f [ k ] + c [ k ] ∗ t [ i ] − c [ k ] ∗ ( t [ k ] − s ) <= f [ j ] + c [ j ] ∗ t [ i ] − c [ j ] ∗ ( t [ j ] − s )

=> f[k]+c[k]∗t[i]−c[k]∗t[k]+c[k]∗s<=f[j]+c[j]∗t[i]−c[j]∗t[j]+c[j]∗s f [ k ] + c [ k ] ∗ t [ i ] − c [ k ] ∗ t [ k ] + c [ k ] ∗ s <= f [ j ] + c [ j ] ∗ t [ i ] − c [ j ] ∗ t [ j ] + c [ j ] ∗ s

=> (f[k]−c[k]∗t[k]+c[k]∗s)−(f[j]−c[j]∗t[j]+c[j]∗s)<=(c[j]−c[k])∗t[i] ( f [ k ] − c [ k ] ∗ t [ k ] + c [ k ] ∗ s ) − ( f [ j ] − c [ j ] ∗ t [ j ] + c [ j ] ∗ s ) <= ( c [ j ] − c [ k ] ) ∗ t [ i ]

=> ((f[k]−c[k]∗t[k]+c[k]∗s)−(f[j]−c[j]∗t[j]+c[j]∗s))/(c[j]−c[k])<=t[i] ( ( f [ k ] − c [ k ] ∗ t [ k ] + c [ k ] ∗ s ) − ( f [ j ] − c [ j ] ∗ t [ j ] + c [ j ] ∗ s ) ) / ( c [ j ] − c [ k ] ) <= t [ i ]

然後用cdq分治優化即可。

細節詳見代碼。

#include<cstdio>
#include<cmath>
#include<algorithm>
typedef long long ll;
using namespace std;
const int N=;
int n,q[N];
ll s,f[N];
struct data{
    ll t,c;
    int id;
    friend bool operator < (const data &a,const data &b){
        return a.t<b.t;
    }
}a[N],b[N];
inline int rd(){
    register int res=,f=;
    register char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-'){
            f=-;
        }
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        res=res*+ch-'0';
        ch=getchar();
    }
    return res*f;
}
ll get(int i){
    return f[a[i].id]-a[i].c*a[i].t+a[i].c*s;
}
ll getx(int j,int k){
    return get(k)-get(j);
}
ll gety(int j,int k){
    return a[j].c-a[k].c;
}
void solve(int l,int r){
    if(l==r){
        return;
    }
    register int mid=(l+r)/,j=l,k=mid+;
    for(register int i=l;i<=r;i++){
        if(a[i].id<=mid){
            b[j++]=a[i];
        }else{
            b[k++]=a[i];
        }
    }
    for(register int i=l;i<=r;i++){
        a[i]=b[i];
    }
    solve(l,mid);
    j=,k=;
    for(register int i=l;i<=mid;i++){
        while(j<k&&getx(q[k],i)*gety(q[k-],q[k])<getx(q[k-],q[k])*gety(q[k],i)){
            k--;
        }
        q[++k]=i;
    }
    for(register int i=mid+;i<=r;i++){
        while(j<k&&getx(q[j],q[j+])<=a[i].t*gety(q[j],q[j+])){
            j++;
        }
        if(j<=k){
            f[a[i].id]=min(f[a[i].id],f[a[q[j]].id]+a[q[j]].c*(a[i].t-a[q[j]].t+s));
        }
    }
    solve(mid+,r);
    j=l,k=mid+;
    for(register int i=l;i<=r;i++){
        if(j<=mid&&(k>r||a[j].c>=a[k].c)){
            b[i]=a[j++];
        }else{
            b[i]=a[k++];
        }
    }
    for(register int i=l;i<=r;i++){
        a[i]=b[i];
    }
}
signed main(){
    scanf("%d%lld",&n,&s);
    for(register int i=;i<=n;i++){
        scanf("%lld%lld",&a[i].t,&a[i].c);
        a[i].t+=a[i-].t;
        a[i].c+=a[i-].c;
        a[i].id=i;
    }
    ll tmp=a[n].c;
    for(register int i=n;i>=;i--){
        a[i].c=tmp-a[i].c;
    }
    for(register int i=;i<=n;i++){
        f[i]=a[].c*(a[i].t+s);
    }
    sort(a+,a+n+);
    solve(,n);
    printf("%lld",f[n]);
    return ;
}