BZOJ 2119: 股市的预测 SA
2119: 股市的预测
Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 434 Solved: 200
[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
题意:趋势跟斜率有关,既然单位时间为1,那斜率只与Δy有关,差分之后再丢掉第一个点,变成了求 ABA 这样子串个数。|B|=m,|A|>0
想法:求ABA,先想到两个暴力:
1、枚举区间,SA+ST O(1)判断。O(n^2)
2、枚举长度以及起点,O(n^2)
然后优化第二个:不枚举起点。每隔 L 长度就设置一个哨兵。如果枚举起点的话,所有ABA中第一个A都会经过这个哨兵,并且是连续的。
于是可以这样统计多少个起点合法:L=lcs([1...x],[1...x+l+m]),R=lcp([x....n],[x+l+m...n]。防止越界没有保证|B|=m,L=min(L,l),R=min(R,l)
ans+=L+R-l。
所以一个哨兵O(1)回答,共(n/1+n/2+n/3.....1)≈O(nlogn)个哨兵。最后复杂度O(nlogn)。
记得要离散....
#include<cstdio>
#include<cstring>
#include<algorithm> typedef long long ll;
const int len();
ll a[len+],d[len+],ans;
int n,B,id[len+];
struct AXLE
{
ll a[len+];int up;
void deal()
{
for(int i=;i<=n;i++)a[++up]=d[i];
std::sort(a+,a++up);
int _up=;
for(int i=;i<=up;i++)if(a[i]!=a[i-])a[++_up]=a[i];
up=_up;
}
int two(ll x)
{
int ans=up;
for(int l=,r=up,mid;l<=r;)
if(a[mid=(l+r)>>]<=x)l=mid+,ans=mid;else r=mid-;
return ans;
}
}axle; int cnt[len+],tmp[len+],p[len+],f[][len+],logg[len+];
void swap(int &x,int &y){x^=y;y^=x;x^=y;}
int min(int a,int b){return a>b?b:a;}
int max(int a,int b){return a<b?b:a;}
void Fdeal()
{
logg[]=-;
for(int i=;i<=n;i++)logg[i]=logg[i>>]+,f[][i]=i+;
for(int j=;j<=logg[n];j++)
for(int i=;i<=n;i++)f[j][i]=f[j-][ f[j-][i] ];
}
struct SA
{
int str[len+],now,limt;
int sfa[len+],rank[len+],height[len+];
void put(int ty)
{
if(ty)for(int i=;i<=n;i++)str[i]=d[i];
else for(int i=;i<=n;i++)str[i]=d[n-i+];
now=n;limt=axle.up;
// fprintf(stderr,"now=%d\n",now);
}
bool cmp(int x,int y,int l){return x+l<=now&&y+l<=now&&rank[x]==rank[y]&&rank[x+l]==rank[y+l];}
void doubling()
{
// fprintf(stderr,"doubling\n");
// fprintf(stderr,"now=%d\n",now);
for(int i=;i<=now;i++)rank[i]=str[i],sfa[i]=i;
for(int l=,pos=,sigma=limt;pos<now;sigma=pos)
{
pos=;
for(int i=now-l+;i<=now;i++)p[++pos]=i;
for(int i=;i<=now;i++)if(sfa[i]>l)p[++pos]=sfa[i]-l;
memset(cnt,,sizeof(int)*(sigma+)); pos=;
for(int i=;i<=now;i++)cnt[rank[i]]++;
for(int i=;i<=sigma;i++)cnt[i]+=cnt[i-];
for(int i=now;i>=;i--)sfa[cnt[rank[p[i]]]--]=p[i];
for(int i=;i<=now;i++)tmp[sfa[i]]=cmp(sfa[i],sfa[i-],l)?pos:++pos;
for(int i=;i<=now;i++)rank[i]=tmp[i];
l=!l?:l<<;
}
for(int i=;i<=now;i++)rank[sfa[i]]=i;
for(int i=,j,k;i<=now;i++)
{
k=sfa[rank[i]-]; if(!k)continue;
j=height[rank[i-]]; if(j)j--;
while(str[i+j]==str[k+j])
j++;
height[rank[i]]=j;
}
// fprintf(stderr,"now=%d\n",now);
// for(int i=1;i<=now;i++)
// fprintf(stderr,"h=%d\n",height[i]);
}
int g[][len+];
//lcp(x,y)=min[x,y-1]
void Gdeal()
{
for(int i=;i<=now;i++)g[][i]=height[i+];
for(int j=;j<=logg[now];j++)
for(int i=;i<=now;i++) g[j][i]=min(g[j-][i],g[j-][ f[j-][i] ]);
}
int lcp(int x,int y)
{
// fprintf(stderr,"1:x= %d y=%d\n",x,y);
x=rank[x];y=rank[y];
if(x>y)swap(x,y); y--;
// fprintf(stderr,"2:x= %d y=%d\n",x,y);
// for(int i=x+1;i<=y;i++)
// fprintf(stderr,"3:h=%d\n",height[i]);
int k=logg[y-x+];
int w=<<k;
return min(g[k][x],g[k][y-w+]);
}
void build(int ty)
{
put(ty); doubling(); Gdeal();
}
}pre,suc;
int main()
{
scanf("%d %d",&n,&B);
for(int i=;i<=n;i++)scanf("%lld",a+i),d[i-]=a[i]-a[i-];
n--;axle.deal();
// fprintf(stderr,"n=%d B=%d\n",n,B);
for(int i=;i<=n;i++)d[i]=axle.two(d[i]);
Fdeal(); pre.build(); suc.build();
for(int l=,LL,RR;l+l+B<=n;l++)
for(int i=l,x,y;i+l+B-<=n;i+=l)
{
// fprintf(stderr,"x= %d y= %d\n",i,i+l+B);
x=i; y=i+l+B;
LL=pre.lcp(n-y+,n-x+); RR=suc.lcp(x,y);
// fprintf(stderr,"LL= %d RR= %d l=%d\n",LL,RR,l);
ans+=max(,min(LL,l)+min(RR,l)-l);
// fprintf(stderr,"ans=%lld\n",ans);
}
printf("%lld",ans);
return ;
}
BZOJ 2119: 股市的预测 SA的更多相关文章
- BZOJ 2119: 股市的预测 [后缀数组 ST表]
2119: 股市的预测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 331 Solved: 153[Submit][Status][Discuss ...
- bzoj 2119: 股市的预测
Description 墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势.股票折线图是研究股票的必备工具,它通过一张时间与股票的价位的函数图像清晰地展示了股票的走势情况.经过长时 ...
- ●BZOJ 2119 股市的预测
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2119 题解: 这个题很好的. 首先把序列转化为差分序列,问题转化为找到合法的子序列,使得去除 ...
- bzoj 2119 股市的预测——枚举长度的关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 就是找差分序列上中间差 m 的相等的两段. 考虑枚举这样一段的长度 L .可以把序列分 ...
- bzoj 2119 股市的预测 —— 枚举关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 思路就是对于这个形如 ABA 的串,枚举 A 的长度,并按照长度分出几块,找到一些关键 ...
- BZOJ 2119 股市的预测 (后缀数组+RMQ)
题目大意:求一个字符串中形如$ABA$的串的数量,其中$B$的长度是给定的 有点像[NOI2016]优秀的拆分这道题 先对序列打差分,然后离散,再正反跑$SA$,跑出$st$表 进入正题 $ABA$串 ...
- BZOJ 2119 股市的预测(后缀数组)
首先要差分+离散化. 然后就是求形如ABA的串有多少,其中B的长度确定为k. 我们用到了设置关键点的思想.我们枚举A的长度L.然后在\(1,1+L,1+L*2,1+L*3...\)设置关键点.然后我们 ...
- BZOJ 2119: 股市的预测 (Hash / 后缀数组 + st表)
转博客大法好 自己画一画看一看,就会体会到这个设置关键点的强大之处了. CODE(sa) O(nlogn)→1436msO(nlogn)\to 1436msO(nlogn)→1436ms #inclu ...
- 【BZOJ 2119】 2119: 股市的预测 (后缀数组+分块+RMQ)
2119: 股市的预测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 404 Solved: 188 Description 墨墨的妈妈热爱炒股,她 ...
随机推荐
- 《Java多线程编程核心技术》读后感(十五)
线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在与State枚举类中. 验证New,Runnable,Terminated new:线程实例化后还从未执行start()方法时的状态 r ...
- CI框架中,扩展验证码类。
使用CI框架的朋友,应该都知道CI框架的的验证码辅助函数,不太好用.它需要写入到数据库中,然后再进行比对. 大家在实际项目中,好像不会这样去使用,因为会对数据库造成一定的压力. 所以,我们还是利用se ...
- 以交互方式将文本添加到图形中(matlab)
这篇博客记录一下怎么用matlab在图形中简单的添加一些文本,以直方图均衡化为例.先看几张图片吧,第一幅是较暗的花粉的电子显微图像和对应的直方图,第二幅是其直方图均衡化的图像和对应的直方图,第三幅是对 ...
- ZOJ 1586 QS Network Kruskal求最小生成树
QS Network Sunny Cup 2003 - Preliminary Round April 20th, 12:00 - 17:00 Problem E: QS Network In the ...
- PhpStorm之三种视图模式
全屏模式 允许你使用整个屏幕编写代码,在视图中移除了所有菜单,同样也移除了操作系统控制栏.然而,你可以继续使用右键菜单和快捷键.当你把鼠标悬停到屏幕顶部时仍然可以看到主菜单. 演示模式 这个模式和全屏 ...
- uoj#349. 【WC2018】即时战略(动态点分治)
传送门 头一次看着题解有一种咱不会\(c++\)的感觉-- 看题解吧-- //minamoto #include<bits/stdc++.h> #include "rts.h&q ...
- IT兄弟连 Java语法教程 编写Java源代码
现在我们来一步一步的编写第一个Java程序,鼎鼎大名的“HelloWorld”. 编写Java源代码 编写Java源代码可以使用任何无格式的文本编辑器,在Windows操作系统上可以使用记事本.Edi ...
- GHOST操作
通过详细的图文说明,怎么用ghost备份系统,以备系统中毒或者感觉不好用时,快速恢复到备份时的状态! 工具/原料 2013最新雨林木风ghostxpxp3系统或者老毛桃等工具 方法/步骤 1 重新启动 ...
- Jquery基本教程(背还是要背的)
Jquery入门学习 一.简介 1.Jquery是基于JavaScript的一种框架,兼容主流浏览器,提供了dom,animate(JQ+CSS),ajax; 2.Jquery2.0后版本不支持IE6 ...
- CC05:基本字符串压缩
题目 利用字符重复出现的次数,编写一个方法,实现基本的字符串压缩功能.比如,字符串"aabcccccaaa"经压缩会变成"a2b1c5a3".若压缩后的字符串没 ...