HDU3045 Picnic Cows

题目

题目

思路

我们先按从小到大排序,显然没错,又是显然答案的方案是连续的
d p i dp_i dpi为前i个的最优解。
dp方程:
d p i = m i n ( d p j + s i − s j − a j + 1 ∗ ( i − j ) ) , 1 < = j < = i − t + 1 dp_i=min(dp_j+s_i-s_j-a_{j+1}*(i-j)),1<=j<=i-t+1 dpi=min(dpj+sisjaj+1(ij)),1<=j<=it+1
因为 ∗ ( i − j ) *(i-j) (ij)我们不能单调队列优化,所以我们考虑斜率优化。
设对i来说,从k断开比j优,则有:
d p j − d p k + s k − s j + j ∗ a j + 1 − k ∗ a k + 1 < = i ∗ ( a j + 1 − a k + 1 ) dp_j-dp_k+s_k-s_j+j*a_{j+1}-k*a_{k+1} <= i*(a_{j+1}-a_{k+1}) dpjdpk+sksj+jaj+1kak+1<=i(aj+1ak+1)
然后就是喜闻乐见的代码了
code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<queue>
#include<deque>
#define int long long
using namespace std;
int n,t,a[400001],s[400001],f[400001],u[400001],l,r,i,j;
int y(int x,int y)
{
 return f[x]-s[x]+x*a[x+1]-(f[y]-s[y]+y*a[y+1]);
}
int x(int x,int y)
{
 return a[x+1]-a[y+1];
}
int dp(int x,int y)
{
 return f[y]+(s[x]-s[y])-a[y+1]*(x-y);
}
signed main()
{
 while (cin>>n>>t)
 {
  for (i=1;i<=n;i++) cin>>a[i];
  memset(f,0,sizeof(f));
  l=r=0;
  u[r++]=0;
  sort(a+1,a+n+1);
  for (i=1;i<=n;i++) s[i]=s[i-1]+a[i];
  for (i=1;i<=n;i++)
  {
   while (l+1<r&&y(u[l+1],u[l])<=i*x(u[l+1],u[l])) l++;
   f[i]=dp(i,u[l]);
   j=i-t+1;
   if (j<t) continue;
   while (l+1<r&&y(j,u[r-1])*x(u[r-1],u[r-2])<=y(u[r-1],u[r-2])*x(j,u[r-1])) r--;
   u[r++]=j;
  }
  cout<<f[n]<<endl;
 }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值