题意很简单,给你若干个数字,你需要减去一些数字,使得在数列中的每个数字出现的次数不少于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. 20155330 2016-2017-2 《Java程序设计》第三周学习总结

    20155330 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 学习目标 区分基本类型与类类型 理解对象的生成与引用的关系 掌握String类和数组 理解封 ...

  2. WPF中。。DataGrid 实现时间控件和下拉框控件

    DatePicker 和新的 DataGrid 行 用户与 DataGrid 中日期列的交互给我造成了很大的麻烦. 我通过将一个 Data Source 对象拖动到 WPF 窗口上,创建了一个 Dat ...

  3. js想不通的地方

    1.js函数的function() 为什么能接受那么多参数,这些参数的名字顺序必须固定还是怎么? 怎么知道调用的时候会发送该参数过去?内部原理?手动传输? 2.js对象,json对象,java对象怎么 ...

  4. c++ 参数个数可变的函数

    #include <stdio.h> #include <string.h> #include <stdarg.h> int addnum(int i,...) { ...

  5. apache开启伪静态的方法 php篇

    打开apache的配置文件httpd.conf 找到 #LoadModule rewrite_module modules/mod_rewrite.so 把前面#去掉.没有则添加,但必选独占一行,使a ...

  6. [.NET] 使用HttpClient操作HFS (HTTP File Server)

    前言 本篇文章介绍如何使用HttpClient操作HFS (HTTP File Server),为自己留个纪录也希望能帮助到有需要的开发人员.关于HTTP File Server的介绍.安装.设定,可 ...

  7. 关于Eclipse在servlet中连接数据库时出现驱动加载失败的解决

    问题:在队友发来的项目中想将他获取到的数据通过数据库储存,出现驱动加载失败问题 解决:首先百度了下相关情况,大多数都是说下载mysql-connector-java-5.1.39-bin.jar包,然 ...

  8. CentOS 下 Java 的下载、安装、配置

    CentOS 下 Java 的下载.安装.配置 系统: CentOS 7 x86_64 Java 版本: 1.8.0_171 本文将 Java 目录放在 /usr/local/java 文件夹下,读者 ...

  9. MySQL5.6.14从安装到启动全过程

    1.下载 地址:http://dev.mysql.com/downloads/mysql/ 这里选择的是Linux-Generic平台,下载了MySQL-5.6.14-1.linux_glibc2.5 ...

  10. Codeforces Round #500 (Div. 2) D - Chemical table

    首先我们如果满足三缺一,那么必有同行和同列的点 如果两行有同列的数,我们可以设想,他们最后会全部填充成为两者啥都有的情况 显然这个是个并查集 现在我们有了很多集合,每个集合自己可以进行三缺一操作,但是 ...