[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. vue装逼神器简述

    主要是分享下用vuejs开发项目过程中遇到的问题,vuejs开发的优势和需要注意的地方. 项目主要页面:主页,最新,分类,分类列表,详情页,结果页,斗图(列表,制作页) 效果图: 地址:https:/ ...

  2. js_读【javascript面向对象编程指南】笔记

    写在前面: 工欲善其事,必先利其器.编程的器,是前人总结的经验,常言道站在巨人的肩膀上开发,往往比自己另辟蹊径容易的多.经验藏于书,故有书中自有颜如玉,书中自有黄金屋,我也一度认为读书要花费很多时间, ...

  3. jq_从右向右的滑入滑出效果

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. 【Python学习笔记】使用Python进行主成分分析

    使用sklearn库中的PCA类进行主成分分析. 导入要用到的库,还没有的直接pip安装就好了. from sklearn.decomposition import PCA import numpy ...

  5. Linux线程同步

    1. 线程同步: 当多个控制线程共享相同的内存时,需要确保每个线程看到一致的数据视图.当某个线程可以修改变量,而其他线程也可以读取或者修改这个变量的时候,就需要对这些线程进行同步,以确保他们在访问变量 ...

  6. python基础===如何优雅的写代码(转自网络)

    本文是Raymond Hettinger在2013年美国PyCon演讲的笔记(视频, 幻灯片). 示例代码和引用的语录都来自Raymond的演讲.这是我按我的理解整理出来的,希望你们理解起来跟我一样顺 ...

  7. 如何掌握jQuery插件开发(高能)

    在实际开发工作中,总会碰到像滚动,分页,日历等展示效果的业务需求,对于接触过jQuery以及熟悉jQuery使用的人来说,首先想到的肯定是寻找现有的jQuery插件来满足相应的展示需求.目前页面中常用 ...

  8. 文件上传实现ajax假异步

    $.ajaxFileUpload({ url : getSitePath()+'/jlyElderly/doUpdateImage', secureuri : false,//是否需要安全协议 fil ...

  9. windows server 2012 IIS配置之FTP站点

    原文地址:[原创]winserver2012IIS配置之FTP站点作者:hkmysterious   一.实验拓扑: 使server2012客户计算机通过ftp方式从FTP服务器上下载已上传并共享的文 ...

  10. datatables的学习总结

    $(document).ready(function() { var oTable= $('#dataTables-example').DataTable({ // searching : false ...