题目大意:求一个字符串中形如$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)的更多相关文章

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

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

  2. 【BZOJ-2119】股市的预测 后缀数组

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

  3. BZOJ 2119: 股市的预测 SA

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

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

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

  5. 【BZOJ2119】股市的预测 后缀数组+分块

    [BZOJ2119]股市的预测 Description 墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势.股票折线图是研究股票的必备工具,它通过一张时间与股票的价位的函数图像清晰 ...

  6. ●BZOJ 2119 股市的预测

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

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

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

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

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

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

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

随机推荐

  1. 互联网组织的未来:剖析 GitHub 员工的任性之源

    转自:http://innolauncher.com/github/ 互联网组织的未来:剖析 GitHub 员工的任性之源 This entry was posted in Blogon 一月 4, ...

  2. Fastdfs环境搭建

    环境准备 使用的系统软件 名称 说明 centos 7.x libfatscommon FastDFS分离出的一些公用函数包 FastDFS FastDFS本体 fastdfs-nginx-modul ...

  3. Python JSON - 世界人口图

    世界人口图 从https://datahub.io/网站搜索population,下载世界人口json数据. from pygal.maps.world import COUNTRIES def ge ...

  4. springboot 不使用前端模板直接跳转页面

    1.创建springboot项目 2.在resource 下创建pages文件夹,存放所有页面 3.编写后台代码 4.访问http://localhost:8080/index,即可跳转到页面

  5. APS.NET webform中的isPostBack

    IsPostBack介绍Page.IsPostBack是一个标志:当前请求是否第一次打开. 调用方法为:Page.IsPostBack或者IsPostBack或者this.IsPostBack或者th ...

  6. socketpair和pipe的区别

    http://blog.csdn.net/bingqingsuimeng/article/details/9055499 管道pipe是半双工的,pipe两次才能实现全双工,使得代码复杂.socket ...

  7. 腾讯云 ubuntuservermysql安装和外网訪问

    1 腾讯云 购买ubuntu 默认账户是ubuntu(因为winscp 使用ubuntu没有权限写文件) 因为腾讯云主机ubuntu系统默认username为ubuntu,不喜欢每次做什么都要sudo ...

  8. HDU 1113 Word Amalgamation (map 容器 + string容器)

    http://acm.hdu.edu.cn/showproblem.php?pid=1113 Problem Description In millions of newspapers across ...

  9. Android系统驱动【转】

    本文转载自:http://www.hovercool.com/en/%E6%B7%BB%E5%8A%A0%E9%A9%B1%E5%8A%A8%E6%A8%A1%E5%9D%97#a_.E5.9B.9B ...

  10. 0x3A 博弈论之SG函数

    博弈即玄学啊 (除了nim和二分图博弈什么都不会 算是学了下SG函数吧 这个东西是针对有向图游戏的,相当于把一个局面看作一个点,到达下个局面相当于建一条边 必胜态SG值为0 那么对于一个点,他的SG值 ...