POJ 3709 K-Anonymous Sequence(斜率优化DP)

 

【题目链接】 http://poj.org/problem?id=3709

 

【题目大意】

  给出一个长度为n个非严格单调递增数列,每次操作可以使得其中任意一项减一,
  问现在使得数列中每项数相同的数的数量都大于等于k-1,问最少进行几次操作

 

【题解】

  我们设dp[i]为前i项答案,得到方程dp[i]=min(dp[j]+S[i]-S[j]-aj*(i-j)),
  dp[i]=S[i]+min(dp[j]-S[j]+aj*j-aj*i),为关于i的线性函数,
  所以我们对f(y)=-ax*y+dp[x]-S[x]+ax*x进行斜率优化。

 

【代码】

#include <algorithm>
#include <cstdio>
#include <cstring>
typedef long long LL;
const int MAX_N=500010;
int n,k;
LL a[MAX_N],dp[MAX_N],S[MAX_N],deq[MAX_N];
LL f(int x,int y){return -a[x]*y+dp[x]-S[x]+a[x]*x;}
bool check(int f1,int f2,int f3){
    LL a1=-a[f1],b1=dp[f1]-S[f1]+a[f1]*f1;
    LL a2=-a[f2],b2=dp[f2]-S[f2]+a[f2]*f2;
    LL a3=-a[f3],b3=dp[f3]-S[f3]+a[f3]*f3;
    return (a2-a1)*(b3-b2)>=(b2-b1)*(a3-a2);
}
void solve(){
    for(int i=0;i<n;i++)S[i+1]=S[i]+a[i];
    int s=0,t=1;
    deq[0]=0; dp[0]=0;
    for(int i=k;i<=n;i++){
        if(i-k>=k){
            while(s+1<t&&check(deq[t-2],deq[t-1],i-k))t--;
            deq[t++]=i-k;
        }while(s+1<t&&f(deq[s],i)>=f(deq[s+1],i))s++;
        dp[i]=S[i]+f(deq[s],i);
    }printf("%lld\n",dp[n]);
}int T;
int main(){
	scanf("%d",&T); 
    while(T--){
        scanf("%d%d",&n,&k);
		for(int i=0;i<n;i++)scanf("%lld",&a[i]);
        solve();
    }return 0;
}

转载于:https://www.cnblogs.com/forever97/p/poj3709.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值