题目类型:\(DP\)+\(RMQ\)

传送门:>Here<

题意:给定一个长度为\(N\)的序列,并给出\(M\)次询问。询问区间\([L,R]\)内的最长完美序列。所谓完美序列就是指连续的且内部元素不重复的序列

解题思路

暴力做法:对于每一次询问,用一个队列维护,\(O(n)\)给出答案。因此复杂度是\(O(nm)\)。

考虑能否求出以每个点为结尾的最长完美序列长度\(f[i]\),以及起始位置\(s[i]\)。假设我们已经维护好了一个数组\(lst[i]\)表示数值\(a[i]\)上一次出现的位置。那么\(s[i]\)可以满足转移方程$$s[i]=Max{s[i-1],lst[i]+1}$$其中,\(s[i-1]\)表示以\(i-1\)为结尾的最长完美序列,然而随着元素\(i\)的加入,有可能在\(s[i-1]\)之后存在\(a[i]\),为了避免这种情况,增加\(lst[i]+1\)为底线。

\(lst\)数组并没有简单的方法来维护,那么既然不能\(O(n^2)\),那么开桶好了(记得负数,\(+ad\))

求出\(s[i]\)以后,很明显有$$f[i]=i-s[i]+1$$然后考虑如何应对询问。一个很本能的反应是求出\(Max\{f[l]..f[r]\}\)。然而这不仅慢,也不正确——用\(f[i]\)的前提条件必须是\(s[i] \geq l\)。因此每个点的答案应该是\(Min\{f[i],i-L+1\}\)

然而这样的话复杂度依然是\(O(nm)\),一种思路是进行优化,用\(RMQ\)来\(O(1)\)解答。然而我们没有办法迅速生成所有的\(i-L+1\)。但是不是所有的点都需要考虑\(i-L+1\)?很明显不是,如果一个点的\(s[i] \geq L\)就不需要考虑了。

\(s[i]\)的值有什么特点?容易发现\(s[i]\)是单调不下降的。(不然暴力中,我们是如何用队列进行维护的?)。新加进来的一个点只会导致起始点不动或后移。

因此回到询问中来,所有\(s[i]\geq L\)的点一定都分布在该区间的右侧。因此我们可以二分来找到这个分界点,在分界点的右侧做\(RMQ\)就完全没有任何问题了,我们只需要考虑\(f[i]\)

同样,分布在左侧的节点只需要考虑到\(L\)的距离了。最大的一定是左侧的最右侧的那个点

因此我们先预处理出\(s[i]\),复杂度\(O(n)\)。然后倍增预处理\(O(nlogn)\),对于每次询问需要二分\((mlogn)\)。因此整道题的复杂度是\(O(n+(n+m)logn)\)的

反思

做出本题的关键在于想到维护\(s[i]\),并且看出\(s[i]\)是单调不下降的。而这两点恰好都在暴力中体现了。因此这告诉我们,正解的很多思路都是来源于暴力的。

Code

注意如果二分全都不能满足,那么应该返回\(r+1\)

/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int MAXN = 200010;
const int AD = 1000000;
const int INF = 1061109567;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
int x = 0; int w = 1; register char c = getchar();
for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
if(c == '-') w = -1, c = getchar();
for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
}
int N,M,l,r,m;
int a[MAXN],s[MAXN],lst[MAXN],b[2*AD+100],f[MAXN],st[MAXN][20];
inline int BinarySearch(int l, int r){
int L = l, R = r, Mid, Ans(r+1);
while(L <= R){
Mid = (L + R) / 2;
if(s[Mid] < l){
L = Mid + 1;
}
else{
R = Mid - 1;
Ans = Mid;
}
}
return Ans;
}
inline int RMQ(int l, int r){
if(l>r) return -1;
int k = log(r-l+1) / log(2);
return Max(st[l][k], st[r-(1<<k)+1][k]);
}
int main(){
// freopen(".in","r",stdin);
N = read(), M = read();
for(int i = 1; i <= N; ++i){
a[i] = read();
lst[i] = b[a[i]+AD];
b[a[i]+AD] = i;
}
s[1] = 1;
for(int i = 2; i <= N; ++i){
s[i] = Max(lst[i]+1, s[i-1]);
f[i] = i-s[i]+1;
st[i][0] = f[i];
}
for(int j = 1; (1<<j) <= N; ++j){
for(int i = 1; i+(1<<j)-1 <= N; ++i){
st[i][j] = Max(st[i][j-1], st[i+(1<<(j-1))][j-1]);
}
}
while(M--){
l = read()+1, r = read()+1;
m = BinarySearch(l,r);
printf("%d\n", Max(m-1-l+1, RMQ(m,r)));
}
return 0;
}

[LOJ10121] 与众不同的更多相关文章

  1. 【LOJ10121】与众不同

    [LOJ10121]与众不同 题面 LOJ 题解 这题是_\(tham\)给\(ztl\)他们做的,然而这道题™居然还想了蛮久... 首先可以尺取出一个位置\(i\)上一个合法的最远位置\(pre_i ...

  2. .NET程序员细数Oracle与众不同的那些奇葩点

    扯淡 距上次接触 Oracle 数据库已经是 N 年前的事了,Oracle 的工作方式以及某些点很特别,那会就感觉,这货就是一个奇葩!最近重拾记忆,一直在折腾 Oracle,因为 Oracle 与众不 ...

  3. InstantClick – 快速响应!让你的网站与众不同

    尽管网络带宽不断增加,但网站并没有更快很多.这是因为最大的瓶颈在于页面加载的延迟.InstantClick 是一个很小的 JavaScript 库,大大加速你的网站响应速度. 在访问者点击一个链接之前 ...

  4. 经典网页设计:20个与众不同的国外 HTML5 网站

    大家都都知道, HTML5 具备所有最新的技术和功能,帮助我们创造平滑过渡,花式图像滑块和动画.如果你正在考虑使用HTML5 来设计自己的网站,那么这个集合能够帮助你. 在过去的10年里,网页设计师使 ...

  5. 与众不同 windows phone 8.0 & 8.1 系列文章索引

    [源码下载] [与众不同 windows phone 7.5 (sdk 7.1) 系列文章索引] 与众不同 windows phone 8.0 & 8.1 系列文章索引 作者:webabcd ...

  6. 与众不同 windows phone (34) - 8.0 新的控件: LongListSelector

    [源码下载] 与众不同 windows phone (34) - 8.0 新的控件: LongListSelector 作者:webabcd 介绍与众不同 windows phone 8.0 之 新的 ...

  7. 与众不同 windows phone (35) - 8.0 新的启动器: ShareMediaTask, SaveAppointmentTask, MapsTask, MapsDirectionsTask, MapDownloaderTask

    [源码下载] 与众不同 windows phone (35) - 8.0 新的启动器: ShareMediaTask, SaveAppointmentTask, MapsTask, MapsDirec ...

  8. 与众不同 windows phone (36) - 8.0 新的瓷贴: FlipTile, CycleTile, IconicTile

    [源码下载] 与众不同 windows phone (36) - 8.0 新的瓷贴: FlipTile, CycleTile, IconicTile 作者:webabcd 介绍与众不同 windows ...

  9. 与众不同 windows phone (37) - 8.0 文件系统: StorageFolder, StorageFile, 通过 Uri 引用文件, 获取 SD 卡中的文件

    [源码下载] 与众不同 windows phone (37) - 8.0 文件系统: StorageFolder, StorageFile, 通过 Uri 引用文件, 获取 SD 卡中的文件 作者:w ...

随机推荐

  1. Linux LVM学习总结——Insufficient Free Extents for a Logical Volume

    如下所示,在创建LV的时候,偶尔会遇到"Volume group "xxxx" has insufficient free space (xxxx extents): x ...

  2. ASP.NET Zero--解决方案结构(层)

    解决方案结构(层) 创建和下载项目后,您将具有如下所示的解决方案结构: 解决方案有8个项目: Core项目包含域层类(如 实体 和 域服务). Application项目包含应用程序逻辑(如应用程序服 ...

  3. Kafka相关内容总结(Kafka集群搭建手记)

    简介 Kafka is a distributed,partitioned,replicated commit logservice.它提供了类似于JMS的特性,但是在设计实现上完全不同,此外它并不是 ...

  4. mysql安装和配置(windowns||centos)

    windows10版本安装 1.获取mysql压缩包 https://dev.mysql.com/downloads/mysql/ 2.解压并配置文件my.ini .解压的文件路径 D:\Progra ...

  5. varnish学习以及CDN的原理

    一.varnish学习Web Page Cache: squid --> varnish 程序的运行具有局部性特征: 时间局部性:一个数据被访问过之后,可能很快会被再次访问到: 空间局部性:一个 ...

  6. python离线安装包

    一.用download命令离线下载包  *.whl , 这个方法好像python3.7以上才能用 那么我的requirement.txt内容就是: django==1.8.11 simplejson= ...

  7. HBase源码实战:CreateRandomStoreFile

    /* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agre ...

  8. Ambari Metrics 详解

    Ambari Metrics 原理 Ambari Metrics System 简称为 AMS,它主要为系统管理员提供了集群性能的监察功能.Metrics 一般分为 Cluster.Host 以及 S ...

  9. Jenkins之Job建立-运行本地脚本

    新建一个自由风格的项目,运行本地脚本 1.点击菜单栏中的“新任务” 2.进入该页面后输入一个项目名称,然后选择“构建一个自由风格的软件项目”,滑动到最底端,点击ok(在左下角) 3.进入下图页面后 “ ...

  10. C# for循环或者foreach往List中添加对象的时候前面的数据总被最后加入的覆盖

    昨天我旁边小姐姐遇到一个问题,就是在执行for循环往list添加数据的时候,前面的数据信息总是被后面的数据信息所覆盖.  这样编写就会造成这样的数据效果:(所有的数据都会被覆盖)     问题原因:对 ...