「2017 山东一轮集训 Day4」基因
设置 \(\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」基因的更多相关文章
- Loj #6069. 「2017 山东一轮集训 Day4」塔
Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...
- Loj 6068. 「2017 山东一轮集训 Day4」棋盘
Loj 6068. 「2017 山东一轮集训 Day4」棋盘 题目描述 给定一个 $ n \times n $ 的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置 $ (x, y),(u, ...
- loj6068. 「2017 山东一轮集训 Day4」棋盘 二分图,网络流
loj6068. 「2017 山东一轮集训 Day4」棋盘 链接 https://loj.ac/problem/6068 思路 上来没头绪,后来套算法,套了个网络流 经典二分图 左边横,右边列 先重新 ...
- 「2017 山东一轮集训 Day4」棋盘(费用流)
棋盘模型 + 动态加边 #include<cstdio> #include<algorithm> #include<iostream> #include<cs ...
- [LOJ#6068]. 「2017 山东一轮集训 Day4」棋盘[费用流]
题意 题目链接 分析 考虑每个棋子对对应的横向纵向的极大区间的影响:记之前这个区间中的点数为 \(x\) ,那么此次多配对的数量即 \(x\) . 考虑费用流,\(S\rightarrow 横向区间 ...
- LOJ 6068「2017 山东一轮集训 Day4」棋盘
题意 一个 \(n\times n\) 的棋盘上面有若干障碍物. 定义两个棋子可以互相攻击当且仅当这两个棋子的横坐标或纵坐标相等而且中间不能隔着障碍物.(可以隔棋子) 有 \(q\) 次询问,每次询问 ...
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- 「2017 山东一轮集训 Day5」苹果树
「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...
- 【LOJ#6066】「2017 山东一轮集训 Day3」第二题(哈希,二分)
[LOJ#6066]「2017 山东一轮集训 Day3」第二题(哈希,二分) 题面 LOJ 题解 要哈希是很显然的,那么就考虑哈希什么... 要找一个东西可以表示一棵树,所以我们找到了括号序列. 那么 ...
随机推荐
- # 2018高考&自主招生 - 游记
准备了一整个学期的高考和自主招生终于结束了....从育英出来, 以一个失败者的身份来写游记, 权当为明年的决战提供经验与总结. Day -1, June 5th 下午同学收拾考场, 自己在那里看书.. ...
- Redis数据类型之列表(list)
1. 什么是列表 redis的列表使用双向链表实现,往列表中放元素的时候复杂度是O(1),但是随机访问的时候速度就不行了,因为需要先遍历到指定的位置才可以取到元素. 既然列表是使用链表实现的,那么就说 ...
- 一文掌握关于Java数据结构所有知识点(欢迎一起完善)
在我们学习Java的时候,很多人会面临我不知道继续学什么或者面试会问什么的尴尬情况(我本人之前就很迷茫).所以,我决定通过这个开源平台来帮助一些有需要的人,通过下面的内容,你会掌握系统的Java学习以 ...
- 在Perl中使用Getopt::Long模块来接收用户命令行参数
我们在linux常常用到一个程序需要加入参数,现在了解一下perl中的有关控制参数的函数.getopt.在linux有的参数有二种形式.一种是–help,另一种是-h.也就是-和–的分别.–表示完整参 ...
- JSOI 2017 退役记
意料之中,真的要退役了. 懒得写游记了. Round 2 的时候状态一直不太清醒,最后混了个rank19,准备AFO吧.
- 虚拟机NAT网络设置
1. 虚拟机设置 2. 本地网络设置 3. 本地虚拟网卡设置 4. 安装虚拟机,设置网络为NAT方式即可访问外网.
- 基于TCP协议的聊天室控制台版
我之前写过一篇博客,主要是基于TCP协议实现的聊天室swing版,在此再写一个基于TCP协议实现的聊天室控制台版,便于学习和比较. package 聊天室console版.utils; import ...
- reverse和reverse_copy函数的应用
reverse函数的作用是:反转一个容器内元素的顺序.函数参数:reverse(first,last);//first为容器的首迭代器,last为容器的末迭代器.它没有任何返回值. 这个函数比较简单, ...
- jenkins+docker持续集成实验
在互联网时代,对于每一家公司,软件开发和发布的重要性不言而喻,目前已经形成一套标准的流程,最重要的组成部分就是持续集成(CI)及持续部署.交付(CD).本文基于Jenkins+Docker+Git实现 ...
- 小技巧:tar命令打包目录时,排除文件和目录的命令
今天不巧要用上,百度. tar zcvf fd.tar.gz pardir --exclude=pardir/file1 --exclude=pardir/dir1