POJ3709_K-Anonymous Sequence
题意很简单,给你若干个数字,你需要减去一些数字,使得在数列中的每个数字出现的次数不少于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的更多相关文章
- 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 ...
- Scala的Pattern Matching Anonymous Functions
参考自http://stackoverflow.com/questions/19478244/how-does-a-case-anonymous-function-really-work-in-sca ...
- 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 一个使 ...
- OGG-Oracle同步Sequence
一.需求,使用OGG同步软件,将Oracle 11g Sequence实时同步到19c新库中 参考文档 Implementing replication of cyclic sequences in ...
- oracle SEQUENCE 创建, 修改,删除
oracle创建序列化: CREATE SEQUENCE seq_itv_collection INCREMENT BY 1 -- 每次加几个 STA ...
- Oracle数据库自动备份SQL文本:Procedure存储过程,View视图,Function函数,Trigger触发器,Sequence序列号等
功能:备份存储过程,视图,函数触发器,Sequence序列号等准备工作:--1.创建文件夹 :'E:/OracleBackUp/ProcBack';--文本存放的路径--2.执行:create or ...
- DG gap sequence修复一例
环境:Oracle 11.2.0.4 DG 故障现象: 客户在备库告警日志中发现GAP sequence提示信息: Mon Nov 21 09:53:29 2016 Media Recovery Wa ...
- Permutation Sequence
The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
- [LeetCode] Sequence Reconstruction 序列重建
Check whether the original sequence org can be uniquely reconstructed from the sequences in seqs. Th ...
- [LeetCode] Binary Tree Longest Consecutive Sequence 二叉树最长连续序列
Given a binary tree, find the length of the longest consecutive sequence path. The path refers to an ...
随机推荐
- 20155230 2016-2017-2 《Java程序设计》第四周学习总结
20155230 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 1.使用extends进行扩充继承时private也会被继承但是子类不能在其中直接存取. 2 ...
- 20155333 2016-2017-2 《Java程序设计》第三周学习总结
20155333 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 第四章 类定义时使用class关键词,名称使用Clothes,建立实例要使用new关键词. ...
- day 10 文件
1.文本文件 ,二进制文件 二进制文件:用vi 打开一个图片,MP3,视频 2.文件打开方式 # 重定向 文件不存在 文件存在 r error 文件开头 w 相当于 > 创建 覆盖,删除以前的内 ...
- Swing 解决 idea 找不到创建gui form的问题
果然,寄希望于百度google不如自己动手,还是得吃透文档, 然后就是对于别人的博客要严格对照步骤来,否则都容易达不到效果 这边gui form在idea下找不到创建,百度google一个说的也没有, ...
- Mysql 5.5从零开始学阅读笔记
第一章 1.什么是数据库? 数据库包含两层含义:保管数据的“仓库”,以及数据管理的方法和技术. 2.表 行被称为记录,列被称为字段 3.主键 primary key,用于唯一标识表中的每一条记录,主键 ...
- Laxcus大数据操作系统单机集群版
Laxcus大数据管理系统是我们Laxcus大数据实验室历时5年,全体系全功能设计研发的大数据产品,目前的最新版本是2.1版本.从三年前的1.0版本开始,Laxcus大数据系统投入到多个大数据和云计算 ...
- 算法笔记(c++)--桶排序题目
算法笔记(c++)--桶排序 记得题目是排序,输入n个1-1000的数字然后去重然后排序. 桶排序没毛病 #include<iostream> using namespace std; i ...
- hbase Problem binding to node1/192.168.1.13:16020 : 地址已在使用
这是hbase 从0.9.x升级到1.x后HMaster与HRegionServer端口冲突问题 在hbase升级到1.0.0版本后,默认端口做了改动.其中16020端口是hmaster服务和hreg ...
- USACO 1.5.4 Checker Challenge跳棋的挑战(回溯法求解N皇后问题+八皇后问题说明)
Description 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行,每列,每条对角线(包括两条主对角线的所有对角线)上都至多有一个棋子. 列号 0 1 2 3 4 5 6 ...
- Scrum立会报告+燃尽图(Beta阶段第四次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2386 项目地址:https://coding.net/u/wuyy694 ...