[BZOJ5351]Query on a sequence

题目大意:

给定一个长度为\(n(n\le10^5)\)的数列\(P\),满足\(|P_i|\le10^9\),求满足下列约束的不同的四元组\((a,b,c,d)\)的个数:

  1. \(1\le a\le b<c\le d\le n\);
  2. \(b-a=d-c\);
  3. \(c-b-1=m\),\(m(m>0)\)为给定的数;
  4. \(p_{a+i}=P_{c+i}\)对于所有\(i(0\le i\le b-a)\)均成立。

思路:

对于\(a\)和\(c\),若\(c-a>m\),且对于后缀\(S_a\)和\(S_c\),有\(\operatorname{lcp}(S_a,S_c)\ge c-a-m\),则我们可以求出合法的\(b\)和\(d\)的区间。

首先对于数列建立后缀数组。从大到小枚举\(lcp[i]\),合并其对应的两个后缀\(a\)和\(c\),因为若下一条枚举到的\(lcp[j]\)如果是关于\(c\)的,则由于\(lcp[i]\ge lcp[i]\),它一样可以适用于\(a\)。对于每个连通块用线段树维护数列每个区间内的数开头的每个后缀是否出现。统计时枚举连通块内每一个后缀,枚举它是\(a\)还是\(c\),在线段树上查找区间和即可。

源代码:

#include<cstdio>
#include<cctype>
#include<climits>
#include<algorithm>
inline int getint() {
register char ch;
register bool neg=false;
while(!isdigit(ch=getchar())) neg|=ch=='-';
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=1e5+1;
int n,m,k,s[N],sa[N],rank[N],tmp[N];
std::pair<int,int> lcp[N];
inline bool cmp(const int &i,const int &j) {
if(rank[i]!=rank[j]) return rank[i]<rank[j];
const int ri=i+k<=n?rank[i+k]:-1;
const int rj=j+k<=n?rank[j+k]:-1;
return ri<rj;
}
inline void suffix_sort() {
for(register int i=0;i<=n;i++) {
sa[i]=i;
rank[i]=s[i];
}
for(k=1;k<=n;k<<=1) {
std::sort(&sa[0],&sa[n+1],cmp);
tmp[sa[0]]=0;
for(register int i=1;i<=n;i++) {
tmp[sa[i]]=tmp[sa[i-1]]+!!cmp(sa[i-1],sa[i]);
}
std::copy(&tmp[0],&tmp[n]+1,rank);
}
};
inline void init_lcp() {
for(register int i=0,h=0;i<n;i++) {
if(h>0) h--;
const int &j=sa[rank[i]-1];
while(i+h<n&&j+h<n&&s[i+h]==s[j+h]) h++;
lcp[rank[i]-1]=std::make_pair(-h,rank[i]);
}
}
const int SIZE=N*20;
class SegmentTree {
private:
struct Node {
int val,left,right;
};
Node node[SIZE];
int sz,new_node() {
return ++sz;
}
public:
int root[N];
void insert(int &p,const int &b,const int &e,const int &x) {
node[p=new_node()].val++;
if(b==e) return;
const int mid=(b+e)>>1;
if(x<=mid) insert(node[p].left,b,mid,x);
if(x>mid) insert(node[p].right,mid+1,e,x);
}
int query(const int &p,const int &b,const int &e,const int &l,const int &r) const {
if(r<l) return 0;
if(b==l&&e==r) return node[p].val;
const int mid=(b+e)>>1;
int ret=0;
if(l<=mid) ret+=query(node[p].left,b,mid,l,std::min(mid,r));
if(r>mid) ret+=query(node[p].right,mid+1,e,std::max(mid+1,l),r);
return ret;
}
int merge(const int &x,const int &y) {
if(!x||!y) return x|y;
node[y].val+=node[x].val;
node[y].left=merge(node[x].left,node[y].left);
node[y].right=merge(node[x].right,node[y].right);
return y;
}
};
SegmentTree t;
struct DisjointSet {
int anc[N],min[N],size[N];
int find(const int &x) {
return x==anc[x]?x:anc[x]=find(anc[x]);
}
void reset() {
for(register int i=1;i<=n;i++) {
size[i]=1;
anc[i]=min[i]=i;
}
}
void merge(const int &x,const int &y) {
anc[x]=y;
min[y]=std::min(min[x],min[y]);
size[y]+=size[x];
}
};
DisjointSet djs;
int lim,ans;
inline void merge(int x,int y) {
x=djs.find(x),y=djs.find(y);
if(djs.size[x]>djs.size[y]) std::swap(x,y);
for(register int i=djs.min[x];i<djs.min[x]+djs.size[x];i++) {
ans+=t.query(t.root[y],1,n,std::max(sa[i]+1+m+1,1),std::min(sa[i]+1+lim,n));
ans+=t.query(t.root[y],1,n,std::max(sa[i]+1-lim,1),std::min(sa[i]+1-m-1,n));
}
djs.merge(x,y);
t.merge(t.root[x],t.root[y]);
}
int main() {
n=getint(),m=getint();
for(register int i=0;i<n;i++) s[i]=getint();
s[n]=INT_MIN;
suffix_sort();
init_lcp();
std::sort(&lcp[0],&lcp[n]);
for(register int i=1;i<=n;i++) {
t.insert(t.root[i],1,n,sa[i]+1);
}
djs.reset();
for(register int i=0;i<n;i++) {
lim=-lcp[i].first+m;
merge(lcp[i].second,lcp[i].second-1);
}
printf("%d\n",ans);
return 0;
}

[BZOJ5351]Query on a sequence的更多相关文章

  1. C#/.NET Little Wonders: Use Cast() and OfType() to Change Sequence Type(zz)

    Once again, in this series of posts I look at the parts of the .NET Framework that may seem trivial, ...

  2. HDU 4441 Queue Sequence(优先队列+Treap树)(2012 Asia Tianjin Regional Contest)

    Problem Description There's a queue obeying the first in first out rule. Each time you can either pu ...

  3. LinqToDB 源码分析——生成与执行SQL语句

    生成SQL语句的功能可以算是LinqToDB框架的最后一步.从上一章中我们可以知道处理完表达式树之后,相关生成SQL信息会被保存在一个叫SelectQuery类的实例.有了这个实例我们就可以生成对应的 ...

  4. LinqToDB 源码分析——处理表达式树

    处理表达式树可以说是所有要实现Linq To SQL的重点,同时他也是难点.笔者看完作者在LinqToDB框架里面对于这一部分的设计之后,心里有一点不知所然.由于很多代码没有文字注解.所以笔者只能接合 ...

  5. Elven Postman(BST )

    Elven Postman Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

  6. of

    “查询序列的一个元素” 1. an element of the query sequence (T) 2. an query sequence element (T) "查询序列或者候选序 ...

  7. hdu 5444 Elven Postman 二叉树

    Time Limit: 1500/1000 MS (Java/Others)   Memory Limit: 131072/131072 K (Java/Others) Problem Descrip ...

  8. Regional Changchun Online--Elven Postman(裸排序二叉树)

    Elven Postman Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Tot ...

  9. hdu 5444 Elven Postman

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5444 Elven Postman Description Elves are very peculia ...

随机推荐

  1. SD卡spi读写流程

    SD卡spi读写流程 1.SD卡的命令格式: SD卡的指令由6字节(Byte)组成,如下: Byte1:0 1 x x x x x x(命令号,由指令标志定义,如CMD39为100111即16进制0x ...

  2. cacti (不可以利用yum安装cacti的配置)

    我们如果用yum不可以安装cacti,我们则可以利用tar包来安装!!! //cacti的配置准备 [root@localhost ~]# yum install -y epel-release [r ...

  3. 《Java编程思想》阅读笔记一

    Java编程思想 这是一个通过对<Java编程思想>(Think in java)第四版进行阅读同时对java内容查漏补缺的系列.一些基础的知识不会被罗列出来,这里只会列出一些程序员经常会 ...

  4. HDU-2389

    Rain on your Parade Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 655350/165535 K (Java/Ot ...

  5. node采用的commonJs规范

    AMD与commonJS规范不同 同步加载 主要就是一个输出,一个引入,我也建了两个文件,一个输出文件一个引入文件 export.js ; ; ; function incCounter(){ cou ...

  6. redis之(一)redis的简单介绍

    [一]:概念 --->Redis是一个开源的,高性能的,基于键值对的缓存与存储系统 --->Redis数据库中的多有数据都存储在内存中,由于内存的读写速度远快于硬盘,一秒读写超过10万键值 ...

  7. 比对两个Word文件内容是否一致的C#解决办法

    using System; using System.Windows.Forms; using System.Diagnostics; using Microsoft.Office.Interop.W ...

  8. Jmeter+Jenkins持续集成(Ant运行脚本)

    Jmeter接口测试脚本运行后生成的是jtl(xml)格式的文件,这些文件不具备可读性,所以我们要把他转化为可以阅读的html格式报告. Ant是一个功能强大的打包编译工具.我们使用他的目的是将xml ...

  9. VS Code js编译支持alias

    VS Code 的编译器 其实就是使用的 typescript 编译器,就是以前提到过的 tsserver.js 相应的编译参数可以参考 http://www.typescriptlang.org/d ...

  10. asp.net webform 打造私人后台管理系统(附源码)

    系统简介 git地址:https://github.com/qingfengjun/XSSystem 不少人让我做公司的网站,要求不多,但是需要有一个后台系统,所以就有了开发的动力.也想做个系统自己学 ...