hdu3045 斜率优化

来源:互联网 发布:java设计模式uml 编辑:程序博客网 时间:2024/05/24 07:27

It’s summer vocation now. After tedious milking, cows are tired and wish to take a holiday. So Farmer Carolina considers having a picnic beside the river. But there is a problem, not all the cows consider it’s a good idea! Some cows like to swim in West Lake, some prefer to have a dinner in Shangri-la ,and others want to do something different. But in order to manage expediently, Carolina coerces all cows to have a picnic!
Farmer Carolina takes her N (1

/*首先 sort 从小到大排序。然后 dp[i] 前 i 个数分隔得到的最小值。则  dp[i]= min{dp[j]+(sum[i]-sum[j])-a[j+1](i-j)}    k<=j<i-t+1.之后就是斜率优化了。*/
/*定义状态dp[i]表示排序后前i个数分组后的最小代价。dp[i] = dp[j] + (sum[i] –sum[j]) –a[j+1] * (i-j)dp[i] = dp[k] + (sum[i] –sum[k]) –a[k+1] * (i-k)斜率优化维护一个凸包,使队首的第一个线段的斜率最优需要 dp[j] + (sum[i] –sum[j]) – a[j+1] * (i-j) > dp[k] + (sum[i] –sum[k]) - a[k+1] * (i-k)所以 dp[j] + sum[i] –sum[j] –a[j+1] * i + a[j+1] * j > dp[k] + sum[i] - sum[k] - a[k+1] * i + a[k+1] * k)所以 dp[j] –sum[j] –a[j+1] * i + a[j+1] * j > dp[k] - sum[k] - a[k+1] * i + a[k+1] * k)所以 dp[j] - dp[k] - sum[j] + sum[k] + a[j+1] * j - a[k+1] * k > i * (a[j+1] - a[k+1])     UP > i * DOWN*/
#include<stdio.h>#include<algorithm>using namespace std;typedef long long dnt;const int maxn=400001;int n,T,h,t;int q[maxn];dnt dp[maxn],sum[maxn],a[maxn];inline const dnt read(){    register dnt f=1,x=0;    register char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}    return x*f;}inline dnt dd(int i,int j){    return dp[j]+sum[i]-sum[j]-a[j+1]*(i-j); }inline dnt up(int j,int k){    return dp[j]-sum[j]+a[j+1]*j-dp[k]+sum[k]-a[k+1]*k;}inline dnt down(int j,int k){    return a[j+1]-a[k+1];}int main(){    while(scanf("%d%d",&n,&T)!=EOF){      dp[0]=sum[0]=a[0]= 0;      for(register int i=1;i<=n;i++) a[i]=read();      sort(a+1,a+n+1);      for(register int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];      for(register int i=T;i<=min(2*T-1,n);i++)  dp[i]=sum[i]-i*a[1];        h=1,t=1;      q[t]=0;      for(register int i=2*T-1;i<=n;i++){          while(h<t&&up(q[h+1],q[h])<=i*down(q[h+1],q[h])) h++;          dp[i]=dd(i,q[h]);          int j=i-T+1;          while(h<t&&up(j,q[t])*down(q[t],q[t-1])<=up(q[t],q[t-1])*down(j,q[t])) t--;          q[++t]=j;      }      printf("%I64d\n",dp[n]);    }}
原创粉丝点击