题意很简单,给你若干个数字,你需要减去一些数字,使得在数列中的每个数字出现的次数不少于k次。

一开始我们都会想到是用DP,于是很快我们就可以得出状态为搞定前面i个数所需要花费的最小代价用f[i]表示。

接下来我们可以得到状态转移方程为f[i]=min(f[j]+sum[i]-sum[j]-(i-j)*a[j+1]);j的枚举范围为k到i-k。这是很容易理解的。

但是再看题目我们就会发现这个算法的时间复杂度为O(N^2),题目中N多大500000,根本无法承受。所以需要优化的说。

接下来要说的就是优化了,这个叫做斜率优化的说。我们假设当前要求f[i],那么对于前面的任意两个j1和j2(j1<j2),如果j2优于j1,那么一定满足f[j1]-f[j2]-sum[j1]+sum[j2]+j1*a[j1+1]-j2*a[j2+1]>i*(a[j1+1]-a[j2+1]);这样我们显然可以直接不考虑j1,因为a[j1+1]-a[j2+1]<=0,等式左边是常数,所以随着i的增加,这个等式一定是恒成立的。这是队首的优化。

同时对于每一次入队之前,对于队尾都有一个优化。那就是我们对于将要入队的那个元素和队尾的两个元素x,y(总共三个元素)顺序两两比较,有一种情况就是对于任意的i,只要y比x优,那么z就比y有,用公式表达就是dy(x,y)/dx(x,y)>=dy(y,z)/dx(y,z)。由于除法会有0的情况,所以在程序中间进行判断的时候要写成乘法的形式。(有负数,注意变号的问题)。那么在这种情况下面,y显然是无效的,我们可以直接从队尾把y删除。

你可能会问,队尾的删除操作是不是一定是必须的呢?一开始我也有这个问题,我认为这是不需要的,因为每次比较的都是两个元素,直到我交上去Wa出了翔。没有队尾的删除操作为什么是错的呢?其实是这样的,因为每次在队首的比较我们都是比较的两个元素来决定队首的元素是否有效,但是如果没有队尾的操作,那么队首的操作也是不正确的。因为x(设为队首第一个)在此时优于y(队首第二个),但是这并不能说明x优于队列中的每一个元素,这就是错误的原因。

下面是我的代码,如果你觉得和网上的神牛的代码长得很像的话我没有意见,因为我一开始是不会做,看着别人的代码才写出来的。

 #include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 500500
typedef long long ll;
using namespace std; ll f[maxn],n,m,k,t,a[maxn],sum[maxn],Q[maxn],head,tail; ll dy(ll j1,ll j2)
{
return f[j1]-f[j2]-sum[j1]+sum[j2]+j1*a[j1+]-j2*a[j2+];
}
ll dx(ll j1,ll j2)
{
return a[j1+]-a[j2+];
} int main()
{
scanf("%I64d",&t);
while (t--)
{
scanf("%I64d%I64d",&n,&k);
sum[]=;
for (int i=; i<=n; i++) scanf("%I64d",&a[i]),sum[i]=sum[i-]+a[i];
head=tail=,Q[]=;
for (ll i=; i<=n; i++)
{
while (head<tail && dy(Q[head],Q[head+])>i*dx(Q[head],Q[head+])) head++;
ll j=Q[head],z=i-k+;
f[i]=f[j]+sum[i]-sum[j]-(i-j)*a[j+];
if (z>=k)
{
while (head<tail)
{
ll x=Q[tail-],y=Q[tail];
if (dy(x,y)*dx(y,z)>=dy(y,z)*dx(x,y)) tail--;
else break;
}
Q[++tail]=z;
}
}
printf("%I64d\n",f[n]);
}
return ;
}

下面这个是我自己写的,进行了一些常数的优化,但是时间依然是1s+,知道如何优化才能把时间优化到200ms左右,真是费解。有神牛如果知道了,求告诉我一声。

 #include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 500500
typedef long long ll;
using namespace std; ll f[maxn],n,m,k,t,a[maxn],sum[maxn],Q[maxn],head,tail,pos[maxn],sy[maxn],yy[maxn],cx,cy; ll dy(ll j1,ll j2)
{
return sy[j2]-sy[j1];
}
ll dx(ll j1,ll j2)
{
return a[j1+]-a[j2+];
} int main()
{
scanf("%I64d",&t);
while (t--)
{
scanf("%I64d%I64d",&n,&k);
sum[]=;
for (int i=; i<=n; i++) scanf("%I64d",&a[i]),sum[i]=sum[i-]+a[i];
head=tail=,Q[]=,pos[]=n+;
for (ll i=; i<=n; i++)
{
while (head<tail && i>pos[head]) head++;
ll j=Q[head],z=i-k+;
f[i]=f[j]+sum[i]-sum[j]-(i-j)*a[j+];
if (z>=k)
{
while (head<tail)
{
if (dy(Q[tail],z)>=(pos[tail-]+)*dx(Q[tail],z)) tail--;
else break;
}
Q[++tail]=z;
cx=dx(Q[tail-],Q[tail]),cy=dy(Q[tail-],Q[tail]);
if (cx==)
{
if (cy>=) pos[tail-]=;
else pos[tail-]=n+;
}
else pos[tail-]=cy/cx;//直接保存当前队列中的数的最远的有效位置。不过好像在删除的时候要更新,不过我的没有更新了,不会影响答案。
}
yy[i]=f[i-]-f[i]-sum[i-]+sum[i]+(i-)*a[i]-i*a[i+];
sy[i]=sy[i-]+yy[i];//dy可以叠加,所以只要求和然后相减就可以了。
}
printf("%I64d\n",f[n]);
}
return ;
}

POJ3709_K-Anonymous Sequence的更多相关文章

  1. IIS FTP Server Anonymous Writeable Reinforcement, WEBDAV Anonymous Writeable Reinforcement(undone)

    目录 . 引言 . IIS 6.0 FTP匿名登录.匿名可写加固 . IIS 7.0 FTP匿名登录.匿名可写加固 . IIS >= 7.5 FTP匿名登录.匿名可写加固 . IIS 6.0 A ...

  2. Scala的Pattern Matching Anonymous Functions

    参考自http://stackoverflow.com/questions/19478244/how-does-a-case-anonymous-function-really-work-in-sca ...

  3. A neural chatbot using sequence to sequence model with attentional decoder. This is a fully functional chatbot.

    原项目链接:https://github.com/chiphuyen/stanford-tensorflow-tutorials/tree/master/assignments/chatbot 一个使 ...

  4. OGG-Oracle同步Sequence

    一.需求,使用OGG同步软件,将Oracle 11g Sequence实时同步到19c新库中 参考文档 Implementing replication of cyclic sequences in ...

  5. oracle SEQUENCE 创建, 修改,删除

    oracle创建序列化: CREATE SEQUENCE seq_itv_collection            INCREMENT BY 1  -- 每次加几个              STA ...

  6. Oracle数据库自动备份SQL文本:Procedure存储过程,View视图,Function函数,Trigger触发器,Sequence序列号等

    功能:备份存储过程,视图,函数触发器,Sequence序列号等准备工作:--1.创建文件夹 :'E:/OracleBackUp/ProcBack';--文本存放的路径--2.执行:create or ...

  7. DG gap sequence修复一例

    环境:Oracle 11.2.0.4 DG 故障现象: 客户在备库告警日志中发现GAP sequence提示信息: Mon Nov 21 09:53:29 2016 Media Recovery Wa ...

  8. Permutation Sequence

    The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...

  9. [LeetCode] Sequence Reconstruction 序列重建

    Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. Th ...

  10. [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列

    Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...

随机推荐

  1. 【SQLSERVER】索引的维护优化

    一.索引的利弊   优点: 1.大大加快数据的检索速度: 2.创建唯一性索引,保证数据库表中每一行数据的唯一性: 3.加速表和表之间的连接: 4.在使用分组和排序子句进行数据检索时,可以显著减少查询中 ...

  2. python全栈开发-面向对象-初识

    python_16_day 函数总结: https://www.processon.com/view/link/5b718274e4b0555b39e1055f 面向过程的程序设计的核心是过程(流水线 ...

  3. python编码和小数据池

    python_day_6 一. 回顾上周所有内容一. python基础 Python是一门解释型. 弱类型语言 print("内容", "内容", end=&q ...

  4. [原创软件]PC端与移动端文件信息互通工具

    一个不小心,花了几个小时,就做出来了一个专利,这不科学啊... 软件主要功能: 跨平台(已适配Mac.Windows)远程连接手机端和PC端 远程执行shell命令 远程和本地文件实现互通传输共享 显 ...

  5. dbtool一bug跟踪记

    注:这篇日志是好多年前,我还在从兴公司时写的.现在都从从兴公司离职很久了,从兴也没落了,可惜.看了一下,虽然出现了部分代码,但不至于泄漏什么机密,查bug过程的原理也有可以让新手借鉴的地方,就原文照搬 ...

  6. Siki_Unity_2-3_UGUI_Unity4.6 UI Beta版本入门学习(未学)

    Unity 2-3 UGUI Unity4.6 UI Beta版本入门学习(未学)

  7. datax 执行流程分析

    https://www.jianshu.com/nb/29319571 https://www.jianshu.com/p/b10fbdee7e56

  8. PLSQL变量和类型,流程控制语句,集合

    ---PLSQL 调试授权 GRANT debug any procedure, debug connect session TO scott; --定义变量 declare part_number ...

  9. 如何选择 .NET Framework目标版本

    如何选择 .NET Framework目标版本 简介 .NET Framework是所有 .NET程序赖以运行的基础. 版本 到目前位置 .NET Framework共出了: .NET Framewo ...

  10. html页面中完成查找功能

    最近在搞一个被很多人改了的框架,天天看代码看的头的晕了,不过感觉进步还挺大的,自己做了一个后台可配置前台查看两个库不同数据范围的东西,还挺满意,那天拿出来分享一下,今天先说一个这几天做的功能,就是ht ...