E52 斜率优化DP [SDOI2012]任务安排

视频链接:462 斜率优化DP [SDOI2012]任务安排_哔哩哔哩_bilibili

1. Luogu P2365 任务安排 

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;
const int N=5010;
int n,s,q[N];
LL tim[N],c[N],f[N];

double slope(int i,int j){ 
  return 1.0*(f[i]-f[j])
            /(c[i]==c[j]?1e-9:c[i]-c[j]);
}
int main(){
  scanf("%d%d",&n,&s);
  for(int i=1;i<=n;i++){
    scanf("%d%d",tim+i,c+i);
    tim[i]+=tim[i-1]; c[i]+=c[i-1];
  }
  
  int h=1,t=0;
  for(int i=1;i<=n;i++){
    while(h<t && slope(i-1,q[t])<=slope(q[t],q[t-1])) t--;
    q[++t]=i-1;    
    while(h<t && slope(q[h+1],q[h])<=tim[i]+s) h++;
    int j=q[h];
    f[i]=f[j]+tim[i]*(c[i]-c[j])+s*(c[n]-c[j]);
  }
  printf("%lld\n",f[n]);
} 

2. Luogu P5785 [SDOI2012]任务安排

#include <iostream>
#include <cstring>
#include <algorithm>
#define N 300010
#define LL long long
using namespace std;

int n,s,h=1,t=0,q[N];
LL c[N],tim[N],f[N];

LL dy(int j,int k){return f[j]-f[k];}
LL dx(int j,int k){return c[j]-c[k];}
int find(int i){
  if(h==t) return q[h];
  int l=h-1,r=t+1;
  while(l+1<r){
    int m=l+r>>1;
    if(dy(q[m],q[m-1])<=dx(q[m],q[m-1])*(tim[i]+s)) l=m;
    else r=m;
  }
  return q[l];
}
int main(){
  scanf("%d%d",&n,&s);
  for(int i=1;i<=n;i++){
    scanf("%lld%lld",tim+i,c+i);
    tim[i]+=tim[i-1]; c[i]+=c[i-1];
  }
  
  for(int i=1;i<=n;i++){
    while(h<t && dy(i-1,q[t])*dx(q[t],q[t-1])<=dx(i-1,q[t])*dy(q[t],q[t-1])) t--;
    q[++t]=i-1;    
    int j=find(i);
    f[i]=f[j]+tim[i]*(c[i]-c[j])+s*(c[n]-c[j]);
  }
  printf("%lld\n",f[n]);
}

 

// wa #12#19
#include <iostream>
#include <cstring>
#include <algorithm>
#define N 300010
#define LL long long
using namespace std;

int n,s,h=1,t=0,q[N];
LL c[N],tim[N],f[N];

double slope(int i,int j){ 
  return 1.0*(f[i]-f[j])
            /(c[i]==c[j]?1e-9:c[i]-c[j]);
}
int find(int i){
  if(h==t) return q[h];
  int l=h-1,r=t+1;
  while(l+1<r){
    int m=l+r>>1;
    if(slope(q[m],q[m-1])<=tim[i]+s) l=m;
    else r=m;
  }
  return q[l];
}
int main(){
  scanf("%d%d",&n,&s);
  for(int i=1;i<=n;i++){
    scanf("%lld%lld",tim+i,c+i);
    tim[i]+=tim[i-1]; c[i]+=c[i-1];
  }
  
  for(int i=1;i<=n;i++){
    while(h<t && slope(i-1,q[t])<=slope(q[t],q[t-1])) t--;
    q[++t]=i-1; 
    int j=find(i);
    f[i]=f[j]+tim[i]*(c[i]-c[j])+s*(c[n]-c[j]);
  }
  printf("%lld\n",f[n]);
} 
posted @ 2023-05-04 16:07  董晓  阅读(325)  评论(1编辑  收藏  举报