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 ...
随机推荐
- MYSQL: sql中某一个字段内容为用逗号分割的字符串转换成多条数据
场景: 表名:testsuer id name 1 小红,小李,李红,小法 要结果值为: 1 小红 1 小李 1 李红 1 小法 MYSQL函数解释 ...
- Java中发邮件的6种方法
1.官方标准JavaMail Sun(Oracle)官方标准,功能强大,用起来比较繁琐. 官方资料:http://www.oracle.com/technetwork/java/javamail/in ...
- Map 遍历的几种方法
复习map的过程中想到的,做个简单的记录 public class HashMapTest { public static void main(String args[]) { Map<Inte ...
- ActiveMQ 发送和接收消息
一.添加 jar 包 <dependency> <groupId>org.apache.activemq</groupId> <artifactId>a ...
- mac 隐藏文件显示
显示:defaults write com.apple.finder AppleShowAllFiles -bool true隐藏:defaults write com.apple.finder Ap ...
- BA-设计施工调试流程
工程范围 1.楼宇自控系统的工程设计首先要了解目标建筑物所处的地理环境.建筑物用途.楼宇自控系统的建设目标定位.建筑设备规模与控制工艺及监控范围等工程情况.这些情况一般在工程招标技术文件中介绍,设计者 ...
- C#中的Attribute Property区别
Attribute 一般译作"特性",Property 仍然译为"属性". Attribute 是一种可由用户自由定义的修饰符(Modifier),可以用来修饰 ...
- jqury+animation+setTimeOut实现渐变显示与隐藏动画
初始效果 实现效果 1,编写HTMl结构代码 <div class="box"> <i class="icon"></i> ...
- [SharePoint][SharePoint Designer 入门经典]Chapter11 工作流基础
1.SPS中可以创建的工作流的种类 2.SPD工作流基础 3.创建列表\库工作流 4.创建可重用的工作流 5.利用基于站点的工作流 6.SPD 工作流的限制和注意事项
- POJ 1948
这道题我记得是携程比赛上的一道. 开始时想直接设面积,但发现不可以,改设能否构成三角形.设dp[i][j][k]为前i根木棍构成边长为j和k的三角形,那么转移可以为dp[i][j][k]=dp[i-1 ...