Description

墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势。股票折线图是研究股票的必备工具,它通过一张时间与股票的价位的函数图像清晰地展示了股票的走势情况。经过长时间的观测,墨墨发现很多股票都有如下的规律:之前的走势很可能在短时间内重现!如图可以看到这只股票A部分的股价和C部分的股价的走势如出一辙。通过这个观测,墨墨认为他可能找到了一个预测股票未来走势的方法。进一步的研究可是难住了墨墨,他本想试图统计B部分的长度与发生这种情况的概率关系,不过由于数据量过于庞大,依赖人脑的力量难以完成,于是墨墨找到了善于编程的你,请你帮他找一找给定重现的间隔(B部分的长度),有多少个时间段满足首尾部分的走势完全相同呢?当然,首尾部分的长度不能为零。

Input

输入的第一行包含两个整数N、M,分别表示需要统计的总时间以及重现的间隔(B部分的长度)。接下来N行,每行一个整数,代表每一个时间点的股价。

Output

输出一个整数,表示满足条件的时间段的个数

Sample Input

12 4
1 2 3 4 8 9 1 2 3 4 8 9

Sample Output

6
【样例说明】
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

这个题好劲啊。。。蒟蒻只会打枚举长度和起点的n^2暴力,只有40分。。。

看到了这个形式的暴力,我竟然毫无想法,这不就是和重复旋律4一样的套路吗;

枚举长度L,只考虑L的整数倍的位置,然后对于i和i+m+L,设i为l,i+m+L为r,我们需要求出l和r往左扩展和往右扩展的最大长度;

往右扩展的最大长度为[l,len]和[r,len]这两个后缀的lcp,往左扩展的最大长度为[1,l],[1,r]这两个前缀的lcs,这个可以翻转后变为lcp;z

则长度为lcp+lcs-1(lcp和lcs有一个为0的时候不要减1)的这一段都是相同的,计算一下答案(注意可能算重,所以lcp和lcs的长度要和L取min);复杂度nlogn;

还有一个小坑点,差分数组全为0的时候,那么height数组会求萎,都+N就好了。。。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define RG register
#define ll long long
using namespace std;
const int N=1e6+10;
const int Inf=19260817;
struct data{
int fir,sec,id;
}x[N];
int sa[N],y[N],rnk[N],rk,height[N],len,pre[N],pre2[N],ST[N][20],n,m;
int b[N],a[N];
bool cmp(const data &a,const data &b){
if(a.fir==b.fir) return a.sec<b.sec;
else return a.fir<b.fir;
}
void work2(){
rk=1;y[x[1].id]=rk;
for(RG int i=2;i<=len;i++){
if(x[i-1].fir!=x[i].fir||x[i-1].sec!=x[i].sec) rk++;
y[x[i].id]=rk;
}
}
void work(){
sort(x+1,x+1+len,cmp);work2();
for(RG int i=1;i<=len;i<<=1){
for(RG int j=1;j+i<=len;j++) x[j].fir=y[j],x[j].sec=y[j+i],x[j].id=j;
for(RG int j=len-i+1;j<=len;j++) x[j].fir=y[j],x[j].sec=0,x[j].id=j;
sort(x+1,x+1+len,cmp);work2();
if(rk==len) break;
}
for(int i=1;i<=len;i++) sa[y[i]]=i;
}
void get_height(){
int kk=0;for(RG int i=1;i<=len;i++) rnk[sa[i]]=i;
for(RG int i=1;i<=len;i++){
if(kk) kk--;
int j=sa[rnk[i]-1];
while(a[i+kk]==a[j+kk]) kk++;
height[rnk[i]]=kk;
}
}
void make_ST(){
pre[0]=1;for(int i=1;i<=16;i++) pre[i]=pre[i-1]<<1;
pre2[0]=-1;for(int i=1;i<=len;i++) pre2[i]=pre2[i>>1]+1;
for(RG int i=2;i<=len;i++) ST[i][0]=height[i];
for(RG int j=1;j<=16;j++)
for(RG int i=2;i<=len;i++){
if(i+pre[j]-1<=len){
ST[i][j]=min(ST[i][j-1],ST[i+pre[j-1]][j-1]);
}
}
}
int query(int l,int r){
if(l>r) swap(l,r);
int x=pre2[r-l+1];
return min(ST[l][x],ST[r-pre[x]+1][x]);
}
int LCP(int l,int r){
if(l==r) return len-sa[l];
if(l>r) swap(l,r);
return query(l+1,r);
}
int main(){
scanf("%d%d",&n,&m);n--;
for(RG int i=1;i<=n+1;i++) scanf("%d",&b[i]);
for(RG int i=1;i<=n;i++) a[i]=b[i+1]-b[i]+N;
a[n+1]=Inf;len=n*2+1;for(int i=1;i<=n;i++) a[len-i+1]=a[i];
for(RG int i=1;i<=len;i++) x[i].id=i,x[i].fir=x[i].sec=a[i];
work();get_height();make_ST();int ans=0;
for(RG int L=1;L<=(n-m)/2;L++){
for(RG int i=1;i+L+m<=n;i+=L){
int l=i,r=i+m+L;
int lcp=min(L,LCP(rnk[l],rnk[r]));
int lcs=min(L,LCP(rnk[len-l+1],rnk[len-r+1]));
int le;
if(lcp&&lcs) le=lcp+lcs-1;
else le=lcp+lcs;
if(le>=L) ans+=le-L+1;
}
}
printf("%d\n",ans);
}

  

bzoj 2119: 股市的预测的更多相关文章

  1. BZOJ 2119: 股市的预测 [后缀数组 ST表]

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 331  Solved: 153[Submit][Status][Discuss ...

  2. BZOJ 2119: 股市的预测 SA

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 434  Solved: 200[Submit][Status][Discuss ...

  3. ●BZOJ 2119 股市的预测

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2119 题解: 这个题很好的. 首先把序列转化为差分序列,问题转化为找到合法的子序列,使得去除 ...

  4. bzoj 2119 股市的预测——枚举长度的关键点+后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 就是找差分序列上中间差 m 的相等的两段. 考虑枚举这样一段的长度 L .可以把序列分 ...

  5. bzoj 2119 股市的预测 —— 枚举关键点+后缀数组

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 思路就是对于这个形如 ABA 的串,枚举 A 的长度,并按照长度分出几块,找到一些关键 ...

  6. BZOJ 2119 股市的预测 (后缀数组+RMQ)

    题目大意:求一个字符串中形如$ABA$的串的数量,其中$B$的长度是给定的 有点像[NOI2016]优秀的拆分这道题 先对序列打差分,然后离散,再正反跑$SA$,跑出$st$表 进入正题 $ABA$串 ...

  7. BZOJ 2119 股市的预测(后缀数组)

    首先要差分+离散化. 然后就是求形如ABA的串有多少,其中B的长度确定为k. 我们用到了设置关键点的思想.我们枚举A的长度L.然后在\(1,1+L,1+L*2,1+L*3...\)设置关键点.然后我们 ...

  8. BZOJ 2119: 股市的预测 (Hash / 后缀数组 + st表)

    转博客大法好 自己画一画看一看,就会体会到这个设置关键点的强大之处了. CODE(sa) O(nlogn)→1436msO(nlogn)\to 1436msO(nlogn)→1436ms #inclu ...

  9. 【BZOJ 2119】 2119: 股市的预测 (后缀数组+分块+RMQ)

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 404  Solved: 188 Description 墨墨的妈妈热爱炒股,她 ...

随机推荐

  1. PE文件格式分析

    PE文件格式分析 PE 的意思是 Portable Executable(可移植的执行体).它是 Win32环境自身所带的执行文件格式.它的一些特性继承自Unix的Coff(common object ...

  2. 【转】javascript中的LHS与RHS

    原文链接:http://www.cnblogs.com/yangxiaoguai132/p/5064625.html 最近在学习javascript过程中,接触了LHS与RHS的概念,刚开始的时候有点 ...

  3. 外观模式(Facade)

    外观模式(Facade) 外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中,而外观模式就是将他们的关系放在一个Facade类中,降低了类类之间的耦合 ...

  4. 关于MVC Ajax.BeginForm()异步上传文件的问题

    问题描述: 如果用juqery原生的异步上传方式,只要如下方法即可 $.ajax({ type: "GET", url: "test.json", data: ...

  5. PAT 1002. A+B for Polynomials (25) 简单模拟

    1002. A+B for Polynomials (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue T ...

  6. CCF-201604-1-折点计数

    问题描述 试题编号: 201604-1 试题名称: 折点计数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 给定n个整数表示一个商店连续n天的销售量.如果某天之前销售量在增长 ...

  7. Git命令汇总(基础篇)

    自己用Git有一段时间了,随着项目越来越多,功能分支也随之增加,从简单的基础命令到随心所欲,需要自己不断地去尝试总结,下面来分享一下我的Git使用总结. 本章基础篇主要讲解一些Git代码提交流程和Gi ...

  8. Vue 事件

    一.事件冒泡 方法一.使用event.cancelBubble = true来阻止冒泡 <div @click="show2()"> <input type=&q ...

  9. Docker: 限制容器可用的 CPU

    默认情况下容器可以使用的主机 CPU 资源是不受限制的.和内存资源的使用一样,如果不对容器可以使用的 CPU 资源进行限制,一旦发生容器内程序异常使用 CPU 的情况,很可能把整个主机的 CPU 资源 ...

  10. SSIS中循环遍历组件[Foreach Loop Container]

    背景 每月给业务部门提取数据,每个分公司都要提取一般,先跑SQL,再粘贴到Excel中,然后发邮件给相关的人员.费时费力,还容易粘贴错位.因此,需要通过一个程序完成这些步骤.我首先想到的是通过SSIS ...