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 ...
随机推荐
- Project Euler 29 Distinct powers( 大整数质因数分解做法 + 普通做法 )
题意: 考虑所有满足2 ≤ a ≤ 5和2 ≤ b ≤ 5的整数组合生成的幂ab: 22=4, 23=8, 24=16, 25=3232=9, 33=27, 34=81, 35=24342=16, 4 ...
- [luogu4053 JSOI2007] 建筑抢修 (贪心 优先队列)
传送门 题目描述 小刚在玩JSOI提供的一个称之为"建筑抢修"的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严重的损伤 ...
- 常用前端布局,CSS技巧介绍
常用前端布局,CSS技巧介绍 对前端常用布局的整理总结,并对其性能优劣,兼容等情况进行介绍 css常用技巧之可变大小正方形的绘制 1:若通过设置width为百分比的方式,则高度不能通过百分比来控制. ...
- 【Manthan, Codefest 18 (rated, Div. 1 + Div. 2) A】Packets
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 多重背包的二进制优化. 就是将数量x分成接近log2x份 然后这log2x份能组合成1..x内的所有数字. 从而将多重背包转化成01 ...
- InitializingBean 和 DisposableBean 指定初始化和销毁方法
通过实现 InitializingBean 和 DisposableBean 接口,也可以指定 bean 的初始化和销毁方法 二.Student 类 public class Student impl ...
- rails 安装后调整gem sources 地址
rails 安装后调整gem sources 地址 使用https会有认证的问题: 移除原有的: gem sources --remove https://rubygems.org/ 查看当前的: g ...
- 数据操作的封装--sqlhelper
为了提高软件的灵活性和可维护性,软件的代码须要科学的管理.我们引入了架构这个词.设计模式提醒我们,软件中反复性的代码须要封装起来. 近期在做收费系统时.须要和数据库进行频繁的联系.既然是反复的使用,就 ...
- AS常见的错误
导入的项目使用的gradle版本和本地的要一致,不然会提示类似"Minimum supported Gradle version is 3.3. Current version is 2.1 ...
- ios除去可变字符串中的某些字符
//除去字符串中的"111@" NSMutableString *str = [[NSMutableString alloc]initWithFormat:@"111@s ...
- Android Cocos2dx引擎 prv.ccz/plist/so等优化缓存文件,手把手ida教你逆向project反编译apk库等文件
前段时间在 Android play 上看到一个非常牛逼的 3D 动态天气预报,效果真的非常炫.二话不说动手 dex2jar.bat/apktool 发现这并没 有什么卵用,在核心的地方看见 nati ...