设置 \(\sqrt{n}\) 个关键点,维护出关键点到每个右端点之间的答案以及Pam的左指针,每次暴力向左插入元素即可,为了去重,还需要记录一下Pam上每个节点在每个关键点为左端点插入到时候到最左边出现位置,总复杂度 \(O(n\sqrt{n})\)。

/*program by mangoyang*/
#pragma GCC optimize("Ofast", "inline")
#include<bits/stdc++.h>
#define inf ((int)(1e9))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int f = 0, ch = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 100005;
char s[N];
namespace PAM{
int fa[N], ch[N][26], trans[N][26], len[N], size, tail, head;
inline void init(){
fa[0] = 1, len[1] = -1, tail = head = size = 1;
for(int i = 0; i < 26; i++) trans[0][i] = 1;
}
inline int newnode(int x){ return len[++size] = x, size; }
inline void pushback(int l, int r){
int c = s[r] - 'a', p = tail;
while(r - len[p] - 1 < l || s[r-len[p]-1] != s[r]) p = fa[p];
if(!ch[p][c]){
int np = newnode(len[p] + 2); fa[np] = ch[trans[p][c]][c];
memcpy(trans[np], trans[fa[np]], sizeof(trans[np]));
trans[np][s[r-len[fa[np]]]-'a'] = fa[np], ch[p][c] = np;
}
tail = ch[p][c];
if(len[tail] == r - l + 1) head = tail;
}
inline void pushfront(int l, int r){
int c = s[l] - 'a', p = head;
while(l + len[p] + 1 > r || s[l+len[p]+1] != s[l]) p = fa[p];
if(!ch[p][c]){
int np = newnode(len[p] + 2); fa[np] = ch[trans[p][c]][c];
memcpy(trans[np], trans[fa[np]], sizeof(trans[np]));
trans[np][s[l+len[fa[np]]]-'a'] = fa[np], ch[p][c] = np;
}
head = ch[p][c];
if(len[head] == r - l + 1) tail = head;
}
} int bel[N], pos[700][N], pre[700][N], ans[700][N], ti[N], n, type, Q, Ans, tim; int main(){
read(type), read(n), read(Q);
scanf("%s", s + 1);
int S = (int) min(n, 150), block = (n / S) + (n % S > 0);
PAM::init();
for(int i = 1; i <= n; i++) bel[i] = (i - 1) / S + 1;
for(int i = 1; i <= block; i++){
PAM::tail = PAM::head = 1, ++tim;
for(int j = (i - 1) * S + 1; j <= n; j++){
PAM::pushback((i - 1) * S + 1, j);
if(ti[PAM::tail] != tim) {
ti[PAM::tail] = tim, pos[i][PAM::tail] = j, ans[i][j]++;
}
ans[i][j] += ans[i][j-1], pre[i][j] = PAM::head;
}
}
while(Q--){
int l, r; read(l), read(r);
l ^= Ans * type, r ^= Ans * type, ++tim;
if(bel[l] == bel[r]){
PAM::head = PAM::tail = 1, Ans = 0;
for(int i = l; i <= r; i++){
PAM::pushback(l, i);
if(ti[PAM::tail] != tim) ti[PAM::tail] = tim, Ans++;
}
printf("%d\n", Ans); continue;
}
int c = bel[l] + 1;
PAM::head = pre[c][r], Ans = ans[c][r];
for(int i = (c - 1) * S; i >= l; i--){
PAM::pushfront(i, r);
if(ti[PAM::head] != tim){
ti[PAM::head] = tim;
if(!pos[c][PAM::head] || pos[c][PAM::head] > r) Ans++;
}
}
printf("%d\n", Ans);
}
return 0;
}

「2017 山东一轮集训 Day4」基因的更多相关文章

  1. Loj #6069. 「2017 山东一轮集训 Day4」塔

    Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...

  2. Loj 6068. 「2017 山东一轮集训 Day4」棋盘

    Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...

  3. loj6068. 「2017 山东一轮集训 Day4」棋盘 二分图,网络流

    loj6068. 「2017 山东一轮集训 Day4」棋盘 链接 https://loj.ac/problem/6068 思路 上来没头绪,后来套算法,套了个网络流 经典二分图 左边横,右边列 先重新 ...

  4. 「2017 山东一轮集训 Day4」棋盘(费用流)

    棋盘模型 + 动态加边 #include<cstdio> #include<algorithm> #include<iostream> #include<cs ...

  5. [LOJ#6068]. 「2017 山东一轮集训 Day4」棋盘[费用流]

    题意 题目链接 分析 考虑每个棋子对对应的横向纵向的极大区间的影响:记之前这个区间中的点数为 \(x\) ,那么此次多配对的数量即 \(x\) . 考虑费用流,\(S\rightarrow 横向区间 ...

  6. LOJ 6068「2017 山东一轮集训 Day4」棋盘

    题意 一个 \(n\times n\) 的棋盘上面有若干障碍物. 定义两个棋子可以互相攻击当且仅当这两个棋子的横坐标或纵坐标相等而且中间不能隔着障碍物.(可以隔棋子) 有 \(q\) 次询问,每次询问 ...

  7. Loj #6073.「2017 山东一轮集训 Day5」距离

    Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...

  8. 「2017 山东一轮集训 Day5」苹果树

    「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...

  9. 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)

    [LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...

随机推荐

  1. 4163 hzwer与逆序对 (codevs + 权值线段树 + 求逆序对)

    题目链接:http://codevs.cn/problem/4163/ 题目:

  2. 【C++自我精讲】基础系列六 PIMPL模式

    [C++自我精讲]基础系列六 PIMPL模式 0 前言 很实用的一种基础模式. 1 PIMPL解释 PIMPL(Private Implementation 或 Pointer to Implemen ...

  3. linux 下 genymotion 模拟器不能安装app

    提示: "应用未安装" 解决方法: 下载: Genymotion-ARM-Translation_v1.1.zip 进入genymotion 的tools用adb传进去: ./ad ...

  4. mysql中列的增删改

    增加列: ); ) after id; ) first; 修改列名: ); #change可改名字与字段类型 mysql> alter table a change uid uid int; Q ...

  5. python基础之内置异常对象

    前言 什么叫异常?简单来说就是程序运行发生了预计结果之外的情况从而导致程序无法正常运行.而python解释器将一些常见的异常情况在它发生时打包成一个异常对象,我们可以通过捕捉这些异常对象从而进行处理, ...

  6. C++ 模板特化以及Typelist的相关理解

    近日,在学习的过程中第一次接触到了Typelist的相关内容,比如Loki库有一本Modern C++ design的一本书,大概JD搜了一波没有译本,英文版600多R,瞬间从价值上看到了这本书的价值 ...

  7. Term Term ssh登陆linux后 显示乱码

    setup----terminal----locale----“chinese” OK!!!!!

  8. Workqueue机制的实现

    Workqueue机制中定义了两个重要的数据结构,分析如下: cpu_workqueue_struct结构.该结构将CPU和内核线程进行了绑定.在创建workqueue的过程中,Linux根据当前系统 ...

  9. 在ubuntu 上安装pycharm

    1.首先在官网下载pycharm并进行提取,将提取的文件夹放在/usr下面(或者任意位置) 2.然后vi /etc/hosts 编辑 将0.0.0.0 account.jetbrains.com添加到 ...

  10. 7.Python3标准库--文件系统

    ''' Python的标准库中包含大量工具,可以处理文件系统中的文件,构造和解析文件名,还可以检查文件内容. 处理文件的第一步是要确定处理的文件的名字.Python将文件名表示为简单的字符串,另外还提 ...