• POJ 3709 K-Anonymous Sequence (单调队列优化)


    题意:给定一个不下降数列,一个K,将数列分成若干段,每段的数字个数不小于K,每段的代价是这段内每个数字减去这段中最小数字之和。求一种分法使得总代价最小?

    思路:F[i]表示到i的最小代价。f[i]=min(f[j]+sum[i]-sum[j]-(i-j)*a[j+1]);(i-j>=K)

    对于j1,j2,j1<j2且j2更优得

    f[j1]+sum[i]-sum[j1]-(i-j1)*a[j1+1]>f[j2]+sum[i]-sum[j2]-(i-j2)*a[j2+1]

    得到:

    f[j1]-sum[j1]+a[j1+1]*j1)-(f[j2]-sum[j2]+a[j2+1]*j2)>=i*(a[j1+1]-a[j2+1])

    可以用单调队列维护.

    由于每一层需要K个,所以我们延迟入队的时间.

     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 #define ll long long
     7 long long f[1000005],sum[1000005],a[1000005];
     8 int c[1000005];
     9 int n,K,T;
    10 ll G(int j,int k){
    11     return f[j]-sum[j]+j*a[j+1]-(f[k]-sum[k]+k*a[k+1]);
    12 }
    13 ll S(int j,int k){
    14     return a[j+1]-a[k+1];
    15 }
    16 int main(){
    17     scanf("%d",&T);
    18     while (T--){
    19         scanf("%d%d",&n,&K);
    20         sum[0]=0;
    21         for (int i=1;i<=n;i++) scanf("%I64d",&a[i]);
    22         for (int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i],f[i]=0;
    23         int h=0,t=0;
    24         c[t++]=0;f[0]=0;
    25         for (int i=1;i<=n;i++){
    26             while (h<t-1&&G(c[h],c[h+1])>=i*S(c[h],c[h+1])) h++;    
    27             f[i]=(ll)f[c[h]]+sum[i]-sum[c[h]]-(i-c[h])*a[c[h]+1];        
    28             if (i>=2*K-1) c[t++]=i-K+1;
    29             for (int j=t-2;j>h;j--){
    30              int x=c[j-1],y=c[j],z=c[j+1];
    31              if (G(x,y)*S(y,z)>=G(y,z)*S(x,y)) c[j]=c[--t];
    32              else break;
    33             }
    34         }
    35         printf("%I64d
    ",f[n]);
    36     }
    37 }
  • 相关阅读:
    NS2仿真:公交车移动周期模型及性能分析
    oracle 列行转换
    oracle dmp文件导出与导入
    fire workflow总结
    install mysql on centos7
    java反射机构应用
    table行颜色设置
    maven无法下依赖jar文件的解决方案
    windows环境jprofiler配置监控tomcat
    CAS tomcat6搭建
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5553607.html
Copyright © 2020-2023  润新知