bzoj2119
题意就是差分后求形如ABA的串的个数,B的长度为M
这是2011国家集训队互测的试题,是道好题,我直接给出出题人的题解吧:
对于这种在线性序列上的组合计数问题,我们很容易想到一个工具:分治!分治算法在形如快速排序等地方能顺利优化算法,我们尝试将其运用至本题中。
不妨设过程F(Left,Right)可以统计在区间[Left,Right]中满足条件的子序列的个数。
设Mid为区间[Left,Right]的中点由于分治执行,我们不需要统计那些属于[Left,Mid],[Mid+1,Right]中的子序列,剩下的我们分两种情况讨论。
1、 点Mid∈Q。这种情况由于|Q|非常小,我们可以直接枚举Q的位置,然后我们可以穷举A部分长度,然后后缀数组+RMQ解决这个问题
此时算法多了一个系数M,不过整体仍然可以在O(NMLogN)的复杂度内完成。
2、 点Mid∉Q,这种情况就比较麻烦了,可以表示成如下示意图:


由于Mid的存在,P2被分割成了3份,由于P1=P2,我们把P1也分割成3份,经过仔细观察,我们发现只需要枚举红线的位置即可解决此部分的统计问题。黄色部分的最大匹配值可以通过将整个Mid左面的部分倒置后求LCP可得。而Mid以及绿色部分的匹配值可以直接通过后缀数组+RMQ求的。知道了绿色与黄色部分的最大值后,那么Q的位置个数也可以相应得出,问题得到解决,此部分复杂度为O(NLogN)。
方法三总复杂度为O(NMLogN),为一个非常优秀的算法。
const eps=1e-8;
var s,h,sa,rank:array[..,..] of longint;
sum,a,b,x,y:array[..] of longint;
f:array[..,..,..] of longint;
d:array[..] of longint;
t,mx,ans,i,n,m:longint; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; procedure suffix(k:longint);
var i,j,m,p:longint;
begin
fillchar(sum,sizeof(sum),);
for i:= to n do
inc(sum[s[i,k]]);
for i:= to mx do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[s[i,k]],k]:=i;
dec(sum[s[i,k]]);
end;
p:=;
rank[sa[,k],k]:=;
for i:= to n do
begin
if s[sa[i,k],k]<>s[sa[i-,k],k] then inc(p);
rank[sa[i,k],k]:=p;
end;
m:=p;
j:=;
while m<n do
begin
for i:= to n do
begin
y[i]:=rank[i,k];
sum[i]:=;
end;
p:=;
for i:=n-j+ to n do
begin
inc(p);
x[p]:=i;
end;
for i:= to n do
if sa[i,k]>j then
begin
inc(p);
x[p]:=sa[i,k]-j;
end; for i:= to n do
begin
a[i]:=y[x[i]];
inc(sum[a[i]]);
end;
for i:= to m do
inc(sum[i],sum[i-]);
for i:=n downto do
begin
sa[sum[a[i]],k]:=x[i];
dec(sum[a[i]]);
end;
p:=;
rank[sa[,k],k]:=;
for i:= to n do
begin
if (y[sa[i,k]]<>y[sa[i-,k]]) or (y[sa[i,k]+j]<>y[sa[i-,k]+j]) then inc(p);
rank[sa[i,k],k]:=p;
end;
m:=p;
j:=j shl ;
end;
h[,k]:=;
p:=;
for i:= to n do
begin
if rank[i,k]= then continue;
j:=sa[rank[i,k]-,k];
while (i+p<=n) and (j+p<=n) and (s[i+p,k]=s[j+p,k]) do inc(p);
h[rank[i,k],k]:=p;
if p> then dec(p);
end;
for i:= to n do
f[i,,k]:=h[i,k];
for j:= to t do
for i:= to n do
if i+d[j]-<=n then
f[i,j,k]:=min(f[i,j-,k],f[i+d[j-],j-,k])
else break;
end; function ask(l,r,k:longint):longint;
var p:longint;
begin
if l>r then swap(l,r);
inc(l);
p:=trunc(ln(r-l+)/ln()+eps);
exit(min(f[l,p,k],f[r-d[p]+,p,k]));
end; procedure work(l,r:longint);
var mid,i,j,x,y:longint;
begin
if r-l+<m+ then exit;
mid:=(l+r) shr ;
for i:=mid-m+ to mid do
for j:=i- downto l do
begin
if r-(i+m)+<i-j then break;
if ask(rank[j,],rank[i+m,],)>=i-j then inc(ans);
end; for i:=l to mid-m- do
begin
x:=min(ask(rank[i,],rank[mid,],),mid-i-m);
if (x<) then continue;
y:=ask(rank[n+-i,],rank[n+-mid,],);
y:=min(y-,min(i-l,mid-i-m-));
if y<mid-i-m-x then continue;
ans:=ans+min(x,y-(mid-i-m-x)+);
end;
for i:=mid+m+ to r do
begin
y:=min(i-mid-m,ask(rank[n+-i,],rank[n+-mid,],));
if y< then continue;
x:=ask(rank[i+,],rank[mid+,],);
x:=min(x,min(r-i,i-mid-m-));
if x<i-mid-m-y then continue;
ans:=ans+min(y,x-(i-mid-m-y)+);
end;
work(l,mid-);
work(mid+,r);
end; procedure sort(l,r:longint);
var i,j,x:longint;
begin
i:=l;
j:=r;
x:=a[(l+r) shr ];
repeat
while a[i]<x do inc(i);
while x<a[j] do dec(j);
if not(i>j) then
begin
swap(a[i],a[j]);
swap(b[i],b[j]);
inc(i);
dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end; begin
readln(n,m);
for i:= to n do
read(a[i]);
dec(n);
for i:= to n do
s[i,]:=a[i+]-a[i]; for i:= to n do
begin
a[i]:=s[i,];
b[i]:=i;
end;
sort(,n);
mx:=;
s[b[],]:=;
for i:= to n do
begin
if a[i]<>a[i-] then inc(mx);
s[b[i],]:=mx;
end;
for i:= to n do
s[i,]:=s[n+-i,];
t:=trunc(ln(n)/ln()+eps);
d[]:=;
for i:= to t do
d[i]:=d[i-]*;
suffix();
suffix();
work(,n);
writeln(ans);
end.
bzoj2119的更多相关文章
- BZOJ2119 股市的预测 字符串 SA ST表
原文链接https://www.cnblogs.com/zhouzhendong/p/9069171.html 题目传送门 - BZOJ2119 题意 给定一个股票连续$n$个时间点的价位,问有多少段 ...
- 【BZOJ2119】股市的预测 后缀数组+分块
[BZOJ2119]股市的预测 Description 墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势.股票折线图是研究股票的必备工具,它通过一张时间与股票的价位的函数图像清晰 ...
- 【BZOJ-2119】股市的预测 后缀数组
2119: 股市的预测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 334 Solved: 154[Submit][Status][Discuss ...
- [NOI2016]优秀的拆分&&BZOJ2119股市的预测
[NOI2016]优秀的拆分 https://www.lydsy.com/JudgeOnline/problem.php?id=4650 题解 如果我们能够统计出一个数组a,一个数组b,a[i]表示以 ...
- bzoj千题计划312:bzoj2119: 股市的预测(后缀数组+st表)
https://www.lydsy.com/JudgeOnline/problem.php?id=2119 题意:将给定数组差分后,求ABA形式的字串个数,要求|B|=m,|A|>0 1.后缀数 ...
- bzoj2119 [ZJOI2010]base基站选址
传送门 n年前的考试题,今天才填上…… 听说你们会决策单调性+主席树?然而我多年不写决策单调性,懒得写了……于是就写了一发线段树. 其实线段树应该不难想,毕竟转移是分层转移,并且这个题的转移函数可以快 ...
- bzoj2119 股市的预测
传送门 感觉智商莫名其妙的就变低了……写这题的时候死活想不出来…… 做法其实不难…… 题目要求形如ABA的串的个数,我们可以枚举A的长度,利用标记关键点的方法统计答案.设枚举到的答案为k,每k个点标记 ...
- BZOJ2119: 股市的预测(后缀数组)
Description 墨墨的妈妈热爱炒股,她要求墨墨为她编写一个软件,预测某只股票未来的走势.股票折线图是研究股票的必备工 具,它通过一张时间与股票的价位的函数图像清晰地展示了股票的走势情况.经过长 ...
- BZOJ2534 Uva10829L-gap字符串 字符串 SA ST表
原文链接https://www.cnblogs.com/zhouzhendong/p/9240665.html 题目传送门 - BZOJ2534 题意 有一种形如 $uvu$ 形式的字符串,其中 $u ...
随机推荐
- SOA之(5)——REST的SOA(SOA with REST)概念
REST的SOA(SOA with REST)概念 发展 1992年网站(Web Sites)是在Web浏览器和Web服务器直接通过HTTP传输HTML. 2000年WS-* (Web Service ...
- Python日志输出——logging模块
Python日志输出——logging模块 标签: loggingpythonimportmodulelog4j 2012-03-06 00:18 31605人阅读 评论(8) 收藏 举报 分类: P ...
- FZU2165 v11(带权的重复覆盖)
题意:有n个boss,m种武器,每种武器选用的时候需要有一定的花费ci,然后这个武器可以消灭掉其中一些BOSS,问你消灭完所有的BOSS,需要的最少花费是多少. 当时比赛的时候,看到这题以为是什么网络 ...
- Thread类详解
java.lang 类 Thread java.lang.Object java.lang.Thread 所有已实现的接口: Runnable public class Threadextends O ...
- 如何提高SQL的执行效率
一.因情制宜,建立“适当”的索引 建立“适当”的索引是实现查询优化的首要前提. 索引(index)是除表之外另一重要的.用户定义的存储在物理介质上的数据结构.当根据索引码的值搜索数据时,索引提供了对数 ...
- poj 2449(A*求第K短路)
题目链接:http://poj.org/problem?id=2449 思路:我们可以定义g[x]为源点到当前点的距离,h[x]为当前点到目标节点的最短距离,显然有h[x]<=h*[x](h*[ ...
- poj 2762(强连通+判断链)
题目链接:http://poj.org/problem?id=2762 思路:首先当然是要缩点建新图,由于题目要求是从u->v或从v->u连通,显然是要求单连通了,也就是要求一条长链了,最 ...
- weka平台
weka平台界面简介 纵向排列的四个主要功能 1.探索(写自己的代码) 2.实验(比较算法) 3.可视化 4.命令行 1.探索 先将weka-src.jar文件解压到一个文件夹 将文件夹导入到Elip ...
- iOS开发--控件
iOS知识点整理-提示器 http://www.jianshu.com/p/ac7e13d36e32 iOS知识点整理-RunLoop http://www.jianshu.com/p/e4fc6ac ...
- WaitForSingleObject与WaitForMultipleObjects用法详解(好用,而且进入一个非常高效沉睡状态,只占用极少的CPU时间片)
在多线程下面,有时候会希望等待某一线程完成了再继续做其他事情,要实现这个目的,可以使用Windows API函数WaitForSingleObject,或者WaitForMultipleObjects ...