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 ...
随机推荐
- tkinter菜单图标,工具栏
所用的图片: import tkinter as tk from tkinter import messagebox, filedialog, simpledialog, colorchooser f ...
- day 11 大文件操作
1.f.read(), f.readline(), f.readlines() ##### 1. f.read() 整体读 返回字符串 In [2]: f = open("aaa.py ...
- jsp命名规则
jsp也用驼峰规则命名即可,不要使用下划线,否则在tomcat中容易出现解析错误
- python进程-进阶
进程同步(multiprocessing.Lock(锁机制).multiprocessing.Semaphore(信号量机制).multiprocessing.Event(事件机制)) 在计算机中,有 ...
- Appium+python HTML测试报告(2)——一份报告模板(转)
(原文:https://www.cnblogs.com/fancy0158/p/10055003.html) 适用于python3: 下载地址: 英文:https://pan.baidu.com/s/ ...
- JMeter自学笔记1-环境安装
一.写在前面的话: Jmeter是一款优秀的开源测试工具, 是每位测试工程师进阶过程中,需要熟悉并掌握的一款测试工具,熟练使用Jmeter能大大提高工作效率. Jmeter环境安装需要依赖JDK,所以 ...
- axios封装(二)队列管理
在某些特定的场景(比如 即时搜索 ,表格分页),会频繁的发起ajax请求,而由于ajax是异步API,所以返回的时序并不能够保证,这时候就需要实现一个ajax队列,在相同的请求发起时,取消处理上一个请 ...
- AnyProxy对搜狐汽车app抓包
关于AnyProxy 详细文档链接 http://anyproxy.io/cn/ anyproxy流程图 简要描述 当http请求经过代理服务器时,具体处理过程是: 收集请求所有请求参数,包括meth ...
- Node开发项目管理工具 Grunt 对比 Gulp
转自Gulp vs Grunt 1. Grunt -> Gulp 早些年提到构建工具,难免会让人联想到历史比较悠久的Make,Ant,以及后来为了更方便的构建结构类似的Java项目而出现的Mav ...
- Scrum立会报告+燃尽图(十月十五日总第六次):视频上传及选题介绍工作
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2196 Scrum立会master:田良 一.小组介绍 组长:付佳 组员: ...