题意
给你一个长度为n的字符串,q次询问一个区间内本质不同的回文串的个数。
n⩽100000,q⩽100000n\leqslant 100000,q\leqslant 100000n⩽100000,q⩽100000
解法
考虑用可持久化线段树。
fi,jf_{i,j}fi,j​表示区间[j,i][j,i][j,i]的答案。
尝试找到fi−1到fif_{i-1}到f_{i}fi−1​到fi​的递推关系。
我们建出回文树。
注意到,回文树上每个节点到根可以拆成lognlognlogn个等差数列。
对这lognlognlogn个等差数列稍微分析一下。
你会发现每个等差数列对应着一个从fi−1f_{i-1}fi−1​到fif_ifi​的区间加法。
证明需要用到一些回文串border的理论。
相关资料可以看我的另一篇博客:
https://blog.csdn.net/ezoilearner/article/details/84851672
于是时空复杂度O(nlognlogn)O(nlognlogn)O(nlognlogn)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int type;
int n,q;
#define Maxn 100010
#define V 10000010
char s[Maxn];struct Node{int sum;int ls,rs;
}tree[V];
int root[Maxn],cnt=0;
void Add(int &k,int x,int l,int r,int L,int R){k=++cnt;tree[k]=tree[x];if(l==L&&r==R){tree[k].sum++;return;}int mid=(l+r)>>1;if(R<=mid)Add(tree[k].ls,tree[x].ls,l,mid,L,R);else if(mid<L)Add(tree[k].rs,tree[x].rs,mid+1,r,L,R);else{Add(tree[k].ls,tree[x].ls,l,mid,L,mid);Add(tree[k].rs,tree[x].rs,mid+1,r,mid+1,R);}
}
int Query(int k,int l,int r,int pos){if(l==r)return tree[k].sum;int mid=(l+r)>>1;if(pos<=mid)return Query(tree[k].ls,l,mid,pos)+tree[k].sum;else return Query(tree[k].rs,mid+1,r,pos)+tree[k].sum;
}int maxv[Maxn<<2];
void Modify(int k,int l,int r,int pos,int num){if(l==r){maxv[k]=num;return;}maxv[k]=num;int mid=(l+r)>>1;if(pos<=mid)Modify(k<<1,l,mid,pos,num);else Modify(k<<1|1,mid+1,r,pos,num);
}
int Query(int k,int l,int r,int L,int R){if(l==L&&r==R)return maxv[k];int mid=(l+r)>>1;if(R<=mid)return Query(k<<1,l,mid,L,R);else if(mid<L)return Query(k<<1|1,mid+1,r,L,R);else return max(Query(k<<1,l,mid,L,mid),Query(k<<1|1,mid+1,r,mid+1,R));
}int endpos[Maxn];
int ch[Maxn][26],fail[Maxn],anc[Maxn],fa[Maxn],len[Maxn],l=0;
int last=1,tot=1;
inline int getfail(int x){while(s[l-len[x]-1]!=s[l])x=fail[x];return x;
}
inline void insert(int dir){l++;int tmp=getfail(last);if(!ch[tmp][dir]){tot++;memset(ch[tot],0,sizeof(ch[tot]));len[tot]=len[tmp]+2;fa[tot]=tmp;fail[tot]=ch[getfail(fail[tmp])][dir];ch[tmp][dir]=tot;anc[tot]=((fail[tot]>1&&len[tot]-len[fail[tot]]==len[fail[tot]]-len[fail[fail[tot]]])?anc[fail[tot]]:tot);}last=ch[tmp][dir];
}int head[Maxn],v[Maxn],nxt[Maxn],T=0;
int in[Maxn],out[Maxn],dfk=0;
inline void add_edge(int s,int e){T++;v[T]=e;nxt[T]=head[s];head[s]=T;}
void dfs(int u){in[u]=++dfk;for(int i=head[u];i;i=nxt[i])dfs(v[i]);out[u]=dfk;
}
inline void Build_Tree(){for(register int i=1;i<=n;++i){insert(s[i]-'a');endpos[i]=last;}add_edge(1,0);for(register int i=2;i<=tot;++i)add_edge(fail[i],i);dfs(1);for(register int i=1;i<=n;++i){root[i]=root[i-1];for(register int k=endpos[i];k>1;k=fail[anc[k]]){int l=max(Query(1,1,dfk,in[k],out[k])-len[k]+1,0)+1;int r=i-len[anc[k]]+1;Add(root[i],root[i],1,n,l,r);}Modify(1,1,dfk,in[endpos[i]],i);}
}inline void rd(int &x){x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
}int main(){rd(type);rd(n);rd(q);memset(ch[0],0,sizeof(ch[0]));memset(ch[1],0,sizeof(ch[1]));fail[0]=1;len[1]=-1;anc[0]=0;anc[1]=1;s[0]=-1;scanf("%s",s+1);Build_Tree();int Ans=0,l,r;while(q--){rd(l);rd(r);l=l^(type*Ans);r=r^(type*Ans);printf("%d\n",Ans=Query(root[r],1,n,l));}return 0;
}

[Loj 6070][回文树+可持久化线段树+border理论]基因相关推荐

  1. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

  2. 主席树 - 可持久化线段树

    模板 P3834 [模板]可持久化线段树 2(主席树) 区间求第 \(k\) 大 模板代码 #include<bits/stdc++.h> using namespace std; #de ...

  3. Codeforces1422 F.Boring Queries(根号分治+线段树+可持久化线段树)

    题意: 解法: 如果问题可以离线,那么莫队可以直接冲过去,可惜离不得. 每个数最多只有一个>sqrt的质因子,sqrt(2e5)<90, 开90棵线段树分别维护前90个质因子的区间最大指数 ...

  4. 主席树 || 可持久化线段树 || LCA || BZOJ 2588: Spoj 10628. Count on a tree || Luogu P2633 Count on a tree...

    题面: Count on a tree 题解: 主席树维护每个节点到根节点的权值出现次数,大体和主席树典型做法差不多,对于询问(X,Y),答案要计算ans(X)+ans(Y)-ans(LCA(X,Y) ...

  5. loj6169 相似序列(可持久化线段树)

    题目: https://loj.ac/problem/6169 分析: 如果是要求两段序列全等的话,有一个套路: 对于{a1,a2,a3} {a4,a5,a6} 设一个素数p,那么如果p^a1+p^a ...

  6. SP10628 COT - Count on a tree (树剖+可持久化线段树)

    题意: 给定一个包含 N 个结点的树. 树节点从 1 到 N编号..每个节点有一个整数权值. 我们会要求您执行以下操作: u v k : 询问从节点 u 到 节点 v 的路径上的第k小的权值 输入 在 ...

  7. 解题报告:P3834 【模板】可持久化线段树 2(主席树)详解

    P3834 [模板]可持久化线段树 2(主席树) 题解 P3834 [[模板]可持久化线段树 2(主席树)] 1)静态求第k大数 可持久化线段树,不能用堆的方法存子结点了,所以用指针l表示左儿子r表示 ...

  8. 可持久化线段树——主席树

    前言: 最近心(po)血(yu)来(ya)潮(li)学习了一下主席树.(再不学就落伍了) 主席树,即可持久化线段树,支持维护和查询区间的第\(k\)大(小).区间不同种类个数等,基于线段树的思想之上 ...

  9. BZOJ.3218.a + b Problem(最小割ISAP 可持久化线段树优化建图)

    BZOJ UOJ 首先不考虑奇怪方格的限制,就是类似最大权闭合子图一样建图. 对于奇怪方格的影响,显然可以建一条边\((i\to x,p_i)\),然后由\(x\)向\(1\sim i-1\)中权值在 ...

  10. 【模板】可持久化线段树 1(主席树)

    题目背景 这是个非常经典的主席树入门题--静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个正整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输 ...

最新文章

  1. 【Kuangbin 带你飞系列】 基础dp
  2. QIIME 2教程. 24Python命令行模式Artifact API(2021.2)
  3. 场效应与三极管 电路标识符_看懂这6个提示,轻松搞定恒流源电源电路设计!...
  4. 【Idea无法打开】Idea.bat可以正常打开,双击快捷方式无法打开解决办法
  5. 第一个python命令
  6. latex转word_Latex与word转换及相关问题解决方法
  7. 适合 Kubernetes 初学者的一些实战练习 (三)
  8. server 2008R2 AD域环境中DHCP服务器的授权步骤
  9. discuz 不能上传头像提示can not write to the data/tmp folder
  10. 32位与64位应用程序速度分析
  11. [GO]删除切片的某个值
  12. 大连理工大学计算机视觉实验室,首个镜子分割网络问世,大连理工、鹏城实验室、香港城大出品 | ICCV 2019...
  13. snmp安装及自定义mib
  14. 搭建HTTP Live Streaming直播系统
  15. 解决java导出excel因数据量大占内存的问题
  16. 胡昌泽 day4笔记
  17. python适合小白学吗_有没有适合零基础小白学习的python课程?
  18. TIA博途如何从DB数据块生成源文件或者源文件生成DB数据块?
  19. 顿号、分号;这些标点符号的用法
  20. 青龙面板使用扩展 聚看点

热门文章

  1. python--craps赌博游戏
  2. Microsoft Office XP 中为开发人员新增的功能
  3. 统计学基础12-秩和检验
  4. Quantum LeaPs 例程之Blinky
  5. php人民币转换,PHP 转换人民币数字为大写
  6. amaze 绝对位置 html,amaze ui 的使用详细教程
  7. JavaScript 汉字与拼音互转终极方案 附JS拼音输入法
  8. [LeetCode] 682. Baseball Game 棒球游戏
  9. 房产经纪人拿楼市新政炒作涨价
  10. 吴伯凡-认知方法论-原始舒适区=0认知