BZOJ 2119 股市的预测 (后缀数组+RMQ)
题目大意:求一个字符串中形如$ABA$的串的数量,其中$B$的长度是给定的
有点像[NOI2016]优秀的拆分这道题
先对序列打差分,然后离散,再正反跑$SA$,跑出$st$表
进入正题
$ABA$串有一个神奇的性质
令$A$串长度是$x$
如果我们选取了一个位置$i$,再选取一个位置$i+x+m$
用预处理的$st$表,求出经过它们的,最长的相同子串的起始位置$s$和结束位置$e$
合法的$ABA$串似乎在$[s,e]$之间滑动
有了这个性质,我们再外层枚举长度$x$,在序列中找出一些相隔为$x$的关键点,求滑动窗口的左$A$串部分,每次当且仅当覆盖一个关键点时,能覆盖的最长距离总和
总时间$O(n(lnn+logn))$
别像我一样把RMQ打错还调了20min
#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 50500
#define ll long long
#define uint unsigned int
#define rint register int
#define il inline
#define it map<int,int>::iterator
#define inf 0x3f3f3f3f
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
} int n,m,len,nn;
int lg[N1];
struct SA{
int a[N1],tr[N1],rk[N1],hs[N1],sa[N1],h[N1],f[N1][];
int check(int i,int j,int k){
if(i+k>len||j+k>len) return ;
return (rk[i]==rk[j]&&rk[i+k]==rk[j+k])?:;
}
void Pre()
{
rint i,cnt=;
for(i=;i<=len;i++) hs[a[i]]++;
for(i=;i<=nn;i++) if(hs[i]) tr[i]=++cnt;
for(i=;i<=nn;i++) hs[i]+=hs[i-];
for(i=;i<=len;i++) rk[i]=tr[a[i]],sa[hs[a[i]]--]=i;
for(int k=;cnt<len;k<<=)
{
for(i=;i<=cnt;i++) hs[i]=;
for(i=;i<=len;i++) hs[rk[i]]++;
for(i=;i<=cnt;i++) hs[i]+=hs[i-];
for(i=len;i>=;i--) if(sa[i]>k) tr[sa[i]-k]=hs[rk[sa[i]-k]]--;
for(i=;i<=k;i++) tr[len-i+]=hs[rk[len-i+]]--;
for(i=;i<=len;i++) sa[tr[i]]=i;
for(i=,cnt=;i<=len;i++) tr[sa[i]]=check(sa[i],sa[i-],k)?cnt:++cnt;
for(i=;i<=len;i++) rk[i]=tr[i];
}
for(i=;i<=len;i++){
if(rk[i]==) continue;
for(int j=max(,h[rk[i-]]-);;j++)
if(a[i+j-]==a[sa[rk[i]-]+j-]) h[rk[i]]=j;
else break;
}
for(i=;i<=len;i++) f[i][]=h[i];
for(int j=;j<=lg[len];j++)
for(i=;i+(<<j)-<=len;i++)
f[i][j]=min(f[i][j-],f[i+(<<(j-))][j-]);
}
int query(int i,int j){
int x=rk[i],y=rk[j];
if(x>y) swap(x,y);x++;int _L=y-x+;
if(_L<) return ;
return min(f[x][lg[_L]],f[y-(<<lg[_L])+][lg[_L]]);
}
}p,s;
int a[N1],A[N1],tmp[N1];
int lower(int l,int r,int *t,int val){
int ans=-inf,id,mid;
while(l<=r){
mid=(l+r)>>;
if(t[mid]<=val&&t[mid]>ans) ans=t[mid],id=mid,l=mid+;
else r=mid-;
}return id;
} int main()
{
scanf("%d%d",&n,&m);
rint i,j;len=n-;
for(lg[]=,i=;i<=n;i++) lg[i]=lg[i>>]+;
A[]=gint();
for(i=;i<=n;i++) A[i]=gint(),a[i-]=tmp[i-]=A[i]-A[i-];
sort(tmp+,tmp+len+);
nn=unique(tmp+,tmp+len+)-(tmp+);
for(i=;i<=len;i++) a[i]=lower(,nn,tmp,a[i]);
for(i=;i<=len;i++) s.a[i]=a[len-i+],p.a[i]=a[i];
p.Pre(),s.Pre();
int lx,rx;ll ans=;
for(j=;j<=len;j++)
{
for(i=;i+j+m<=len;i+=j)
{
lx=min(s.query(len-i+,len-(i+j+m)+),j);
rx=min(p.query(i+,i++j+m),j-);
ans+=max(,lx+rx-j+);
}
}
printf("%lld\n",ans);
return ;
}
/*
2 2 2 3 2 1 2 2 2 3 2 1 2 2 2 3 2
2
2 1 2 2 2 3 2
2 2 2 3 2
2 2 2 3 2 1 2 2 2 3 2
2 2 3 2
2 2 3 2 1 2 2 2 3 2
2 3 2
2 3 2 1 2 2 2 3 2
3 2
3 2 1 2 2 2 3 2 2 3 2 2 2 1 2 3 2 2 2 1 2 3 2 2 2
2
2 1 2 3 2 2 2
2 2
2 2 1 2 3 2 2 2
2 2 2
2 2 2 1 2 3 2 2 2
2 3 2 2 2
2 3 2 2 2 1 2 3 2 2 2
3 2 2 2
3 2 2 2 1 2 3 2 2 2
*/
BZOJ 2119 股市的预测 (后缀数组+RMQ)的更多相关文章
- BZOJ 2119: 股市的预测 [后缀数组 ST表]
2119: 股市的预测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 331 Solved: 153[Submit][Status][Discuss ...
- 【BZOJ-2119】股市的预测 后缀数组
2119: 股市的预测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 334 Solved: 154[Submit][Status][Discuss ...
- 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 ...
随机推荐
- IOS开发:使用lipo合并armv7,i386,armv7s库文件
假设多个版本的lib分别是 libxxx.armv7.a , libxxx.armv7s.a, libxxx.i386.a我们的目标是 把他们合并成超级通用版的libxxx.a 打开命令行 Term ...
- P3378 【模板】堆
题目描述 如题,初始小根堆为空,我们需要支持以下3种操作: 操作1: 1 x 表示将x插入到堆中 操作2: 2 输出该小根堆内的最小数 操作3: 3 删除该小根堆内的最小数 输入输出格式 输入格式: ...
- Zend 官方框架增加 Swoole 协程支持 !
前言 Zend Framework 是 PHP 的官方框架,随着 Zend-Expressive-Swoole 0.2.2 的发布,率先支持了 Swoole 4 的协程功能,现在可以仅通过一个配置即可 ...
- POJ 4786 Fibonacci Tree
Fibonacci Tree Time Limit: 2000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ...
- hdu 1868 水
#include<stdio.h> int main() { int n,m,i,j,k; while(scanf("%d",&n)!=EOF) { k=2; ...
- hdu 4607 树形dp 树的直径
题目大意:给你n个点,n-1条边,将图连成一棵生成树,问你从任意点为起点,走k(k<=n)个点,至少需要走多少距离(每条边的距离是1): 思路:树形dp求树的直径r: a:若k<=r+1 ...
- BA-siemens-insight_lenum点
lenum点特性 lenum点有如下特点 如果状态字是自定义的,只能在bacnet / ip的aln层使用 如果想在ms/tp层使用lenum的功能,就必须将system profile中bacnet ...
- HttpClient异步请求Post传递Json
HttpClient异步Post请求,HttpClient.PostAsync(String, HttpContent, CancellationToken),String为Post的Url,Http ...
- HDU 5167
范围 内的斐波那契的数不多,求出范围内的数,再暴力枚举即可. #include <iostream> #include <cstdio> #include <algori ...
- Mysql 奇怪的连接错误
今天,碰到了一个数据库连接问题: 不像之前在linux上mysql连接问题,那是权限设置.而这次问题的起源是: 我想要往mysql导入csv文件,可是因为文件比較大.有88M数据:使用navicatc ...