【BZOJ-2119】股市的预测 后缀数组
2119: 股市的预测
Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 334 Solved: 154
[Submit][Status][Discuss]
Description
墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势。股票折线图是研究股票的必备工具,它通过一张时间与股票的价位的函数图像清晰地展示了股票的走势情况。经过长时间的观测,墨墨发现很多股票都有如下的规律:之前的走势很可能在短时间内重现!如图可以看到这只股票A部分的股价和C部分的股价的走势如出一辙。通过这个观测,墨墨认为他可能找到了一个预测股票未来走势的方法。进一步的研究可是难住了墨墨,他本想试图统计B部分的长度与发生这种情况的概率关系,不过由于数据量过于庞大,依赖人脑的力量难以完成,于是墨墨找到了善于编程的你,请你帮他找一找给定重现的间隔(B部分的长度),有多少个时间段满足首尾部分的走势完全相同呢?当然,首尾部分的长度不能为零。
Input
输入的第一行包含两个整数N、M,分别表示需要统计的总时间以及重现的间隔(B部分的长度)。接下来N行,每行一个整数,代表每一个时间点的股价。
Output
输出一个整数,表示满足条件的时间段的个数
Sample Input
1 2 3 4 8 9 1 2 3 4 8 9
Sample Output
【样例说明】
6个时间段分别是:3-9、2-10、2-8、1-9、3-11、4-12。
HINT
对于100%的数据,4≤N≤50000 1≤M≤10 M≤N 所有出现的整数均不超过32位含符号整数。
Source
Solution
一眼居然没读懂题...
把题目转化一下,差分后,就是求形如$ABA$的子串数目,其中$|B|=K$
这样显然就是可以用后缀数组乱搞,最暴力的方法就是依次枚举$B$的初始位置,然后前后匹配,然后统计入答案。
所以枚举长度,然后对序列分段统计答案。
具体的就是对于枚举的长度$len$,从$1$开始每次枚举的端点$+len$,同时可以直接求出另一端的位置,然后求两端向前向后扩展的LCP即可。
问题在于直接利用LCP求答案会出现重复,所以限制当前端点向前向后统计LCP时不得跨越上一个/下一个枚举到的端点,还需要注意的就是向前向后统计时不要两次统计当前端点。
根据调和级数,这样的枚举的复杂度是$O(NlogN)$,加上后缀数组的$O(NlogN)$,并不影响总复杂度。
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN 100010
int N,K,a[MAXN];
int R[MAXN],SA[MAXN],height[MAXN],rank[MAXN],t1[MAXN],t2[MAXN],st[MAXN];
inline void Sort(int *x,int *y,int *sa,int L,int M)
{
for (int i=0; i<=M; i++) st[i]=0;
for (int i=0; i<L; i++) st[x[y[i]]]++;
for (int i=1; i<=M; i++) st[i]+=st[i-1];
for (int i=L-1; i>=0; i--) sa[--st[x[y[i]]]]=y[i];
}
inline void DA(int *r,int *sa,int L,int M)
{
int *x=t1,*y=t2,*t,i,j,p;
for (int i=0; i<L; i++) x[i]=r[i],y[i]=i;
Sort(x,y,sa,L,M);
for (j=1,p=1; j<L && p<L; j<<=1,M=p-1)
{
for (p=0,i=L-j; i<L; i++) y[p++]=i;
for (i=0; i<L; i++) if (sa[i]>=j) y[p++]=SA[i]-j;
Sort(x,y,sa,L,M);
for (t=x,x=y,y=t,i=1,x[sa[0]]=0,p=1; i<L; i++)
x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]? p-1:p++;
}
}
inline void Height(int *r,int *sa,int *rank,int *h,int L)
{
h[1]=0;
for (int i=1; i<=L; i++) rank[sa[i]]=i;
for (int i=1,k=0,j; i<=L; h[rank[i++]]=k)
for (k? --k:k=0,j=sa[rank[i]-1]; r[j+k]==r[i+k]; k++);
}
int log_2[MAXN],dp[MAXN][21];
inline void St(int L)
{
log_2[0]=-1;
for (int i=1; i<=L; i++)
if (i&(i-1))
log_2[i]=log_2[i-1];
else
log_2[i]=log_2[i-1]+1;
for (int i=0; i<=L; i++) dp[i][0]=height[i+1];
for (int j=1; (1<<j)<=L; j++)
for (int i=0; i+(1<<j)-1<=L; i++)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
inline int RMQ(int l,int r) {int k=log_2[r-l]; return min(dp[l][k],dp[r-(1<<k)][k]);}
inline int LCP(int l,int r) {l=rank[l],r=rank[r]; if (l>r) swap(l,r); return RMQ(l,r);}
int ls[MAXN];
int main()
{
N=read(),K=read();
for (int i=1; i<=N; i++) a[i]=read();
for (int i=1; i<=N-1; i++) ls[i]=R[i]=a[i+1]-a[i];
for (int i=1; i<=N-1; i++) R[N+i]=R[N-1-i+1];
sort(ls+1,ls+N-1+1);
int mx=unique(ls+1,ls+N-1+1)-ls-1;
// for (int i=1; i<=2*N-1; i++) printf("%d ",R[i]); puts("");
for (int i=1; i<=2*N-1; i++) R[i]=lower_bound(ls+1,ls+mx+1,R[i])-ls;
R[N]=mx+1;
// for (int i=1; i<=2*N-1; i++) printf("%d ",R[i]); puts("");
DA(R,SA,2*N-1+1,mx+1); Height(R,SA,rank,height,2*N-1); St(2*N-1);
LL ans=0;
for (int len=1; len*2+K<=N-1; len++)
{
int pre=0,suf=0;
for (int i=1; i+len+K<=N-1; i+=len)
{
suf=min(len,LCP(i,i+len+K));
if (i>1) pre=min(len-1,LCP(2*N-1-i+1+1,2*N-1-(i+len+K)+1+1)); else pre=0;
// printf("%d %d %d %d->",i,i+len+K,2*N-1-i+1,2*N-1-(i+len+K)+1);
if (suf+pre>=len) ans+=(LL)(suf+pre-len+1);
// printf("%d %d %d %d %I64d\n",i,len,pre,suf,ans);
}
}
printf("%lld\n",ans);
return 0;
}
/*
10 1
1 3 7 1 9 5 6 8 4 3
*/
【BZOJ-2119】股市的预测 后缀数组的更多相关文章
- BZOJ 2119: 股市的预测 [后缀数组 ST表]
2119: 股市的预测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 331 Solved: 153[Submit][Status][Discuss ...
- BZOJ 2119 股市的预测 (后缀数组+RMQ)
题目大意:求一个字符串中形如$ABA$的串的数量,其中$B$的长度是给定的 有点像[NOI2016]优秀的拆分这道题 先对序列打差分,然后离散,再正反跑$SA$,跑出$st$表 进入正题 $ABA$串 ...
- BZOJ 2119: 股市的预测 SA
2119: 股市的预测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 434 Solved: 200[Submit][Status][Discuss ...
- BZOJ 2119 股市的预测(后缀数组)
首先要差分+离散化. 然后就是求形如ABA的串有多少,其中B的长度确定为k. 我们用到了设置关键点的思想.我们枚举A的长度L.然后在\(1,1+L,1+L*2,1+L*3...\)设置关键点.然后我们 ...
- 【BZOJ2119】股市的预测 后缀数组+分块
[BZOJ2119]股市的预测 Description 墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势.股票折线图是研究股票的必备工具,它通过一张时间与股票的价位的函数图像清晰 ...
- ●BZOJ 2119 股市的预测
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2119 题解: 这个题很好的. 首先把序列转化为差分序列,问题转化为找到合法的子序列,使得去除 ...
- bzoj 2119 股市的预测 —— 枚举关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 思路就是对于这个形如 ABA 的串,枚举 A 的长度,并按照长度分出几块,找到一些关键 ...
- bzoj 2119 股市的预测——枚举长度的关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 就是找差分序列上中间差 m 的相等的两段. 考虑枚举这样一段的长度 L .可以把序列分 ...
- BZOJ 2119: 股市的预测 (Hash / 后缀数组 + st表)
转博客大法好 自己画一画看一看,就会体会到这个设置关键点的强大之处了. CODE(sa) O(nlogn)→1436msO(nlogn)\to 1436msO(nlogn)→1436ms #inclu ...
随机推荐
- JVM调优总结
堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操作 ...
- atitit.http原理与概论attilax总结
atitit.http原理与概论attilax总结 1. 图解HTTP 作者:[日]上野宣 著1 2. HTTP权威指南(国内首本HTTP及其相关核心Web技术权威著作)1 3. TCP/IP详解(中 ...
- HTML DOM总结
MDN的定义 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口.它给文档(结构树)提供了一个结构化的表述并且定义了一种方式—程序可以对结构树进行访问,以改变文档的结构,样式和内容. ...
- arcgis api for js入门开发系列一arcgis api离线部署
在我的GIS之家QQ群里,很多都是arcgis api for js开发的新手,他们一般都是GIS专业的学生,或者从计算机专业刚刚转向来的giser,他们难免会遇到各种webgis开发的简单问题,由于 ...
- UI篇(初识君面)
我们的APP要想吸引用户,就要把UI(脸蛋)搞漂亮一点.毕竟好的外貌是增进人际关系的第一步,我们程序员看到一个APP时,第一眼就是看这个软件的功能,不去关心界面是否漂亮,看到好的程序会说"我 ...
- Android InputType详解
android:inputType 如果设置android:inputType = "number",则默认弹出的输入键盘为数字键盘,且输入的内容只能为数字. InputType文 ...
- 整理分享原生态mac AndroidStudio的快捷键
使用AndroidStudio开发半年了,一路爬坑至今,刚由Windows转mac一个星期.通过查些资料和自己摸索,记录一些常用的快捷键,犹豫个人不喜欢改快捷键,所以都是原生的.特此分享给大家!欢迎补 ...
- jQuery 获取 radio 选中后的文字
如果html为 <input type="radio" id="test" name="test" value="1&quo ...
- Servlet入门笔记
一.一个简单的Servlet 在servlet 3.0之前,下面是基本步骤: 1.新建一个class名为FirstServlet,让它继承javax.servlet.http.HttpServlet: ...
- 理解Docker(4):Docker 容器使用 cgroups 限制资源使用
本系列文章将介绍Docker的有关知识: (1)Docker 安装及基本用法 (2)Docker 镜像 (3)Docker 容器的隔离性 - 使用 Linux namespace 隔离容器的运行环境 ...