Luogu2336 SCOI2012 喵星球上的点名 SA、莫队
一道很套路的题目
先将所有串拼在一起,两个不同的串之间放一个没有出现在任何串中的字符做分隔,然后SA
那么对于所有点名串能够点到的名字串在SA中对应一段区间
把这些区间拿出来然后莫队统计每一个区间的答案
如何在莫队中统计一个名字在多少个点名串中出现?
当某一个名字第一次出现在区间内的时候,答案加上剩余询问个数;当这个名字第一次不出现在区间内的时候,答案减去剩余询问个数。
#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 5e5 + 9;
int s[MAXN] , rk[MAXN << 1] , pot[MAXN] , tp[MAXN << 1] , sa[MAXN] , h[MAXN];
int N , M , L , maxN = 10001 , T , logg2[MAXN] , ST[21][MAXN];
int lft , cnt , ans1[MAXN] , ans2[MAXN] , times[MAXN] , ind[MAXN];
struct query{
int l , r , ind;
bool operator <(const query a)const{
return l / T == a.l / T ? ((l / T) & 1 ? r > a.r : r < a.r) : l < a.l;
}
}now[MAXN];
void sort(int p){
memset(pot , 0 , sizeof(int) * (maxN + 1));
for(int i = 1 ; i <= L ; ++i)
++pot[rk[i]];
for(int i = 1 ; i <= maxN ; ++i)
pot[i] += pot[i - 1];
for(int i = 1 ; i <= L ; ++i)
sa[++pot[rk[tp[i]] - 1]] = tp[i];
swap(rk , tp);
for(int i = 1 ; i <= L ; ++i)
rk[sa[i]] = rk[sa[i - 1]] + (tp[sa[i]] != tp[sa[i - 1]] || tp[sa[i] + p] != tp[sa[i - 1] + p]);
maxN = rk[sa[L]];
}
void SA(){
for(int i = 1 ; i <= L ; ++i){
rk[i] = s[i];
tp[i] = i;
}
sort(0);
for(int i = 1 ; maxN < L ; i <<= 1){
int cnt = 0;
for(int j = 1 ; j <= i ; ++j)
tp[++cnt] = L - i + j;
for(int j = 1 ; j <= L ; ++j)
if(sa[j] > i)
tp[++cnt] = sa[j] - i;
sort(i);
}
for(int i = 1 ; i <= L ; ++i){
if(rk[i] == 1)
continue;
int t = rk[i];
h[t] = max(0 , h[rk[i - 1]] - 1);
while(s[h[t] + sa[t]] == s[h[t] + sa[t - 1]])
++h[t];
}
}
inline void init_SA(){
N = read();
M = read();
for(int i = 1 ; i <= N ; ++i){
int l = read();
for(int j = 1 ; j <= l ; ++j){
s[++L] = read() + 1;
ind[L] = i;
}
s[++L] = ++maxN;
l = read();
for(int j = 1 ; j <= l ; ++j){
s[++L] = read() + 1;
ind[L] = i;
}
s[++L] = maxN;
}
for(int i = 1 ; i <= M ; ++i){
int l = read();
for(int j = 1 ; j <= l ; ++j){
s[++L] = read() + 1;
ind[L] = j == 1 ? -l : 0;
}
s[++L] = ++maxN;
}
SA();
}
inline void init_ST(){
for(int i = 2 ; i <= L ; ++i){
logg2[i] = logg2[i >> 1] + 1;
ST[0][i] = h[i];
}
for(int i = 1 ; 1 << i <= L ; ++i)
for(int j = 2 ; j + (1 << i) <= L + 1 ; ++j)
ST[i][j] = min(ST[i - 1][j] , ST[i - 1][j + (1 << (i - 1))]);
}
inline int qST(int x , int y){
int t = logg2[y - x + 1];
return min(ST[t][x] , ST[t][y - (1 << t) + 1]);
}
inline void GetQue(int dir){
T = sqrt(L);
++M;
now[M].ind = M;
int L = 1 , R = rk[dir];
while(L < R){
int mid = (L + R) >> 1;
if(qST(mid + 1 , rk[dir]) >= -ind[dir])
R = mid;
else
L = mid + 1;
}
now[M].l = L;
L = rk[dir];
R = L;
while(L < R){
int mid = (L + R + 1) >> 1;
if(qST(rk[dir] + 1 , mid) >= -ind[dir])
L = mid;
else
R = mid - 1;
}
now[M].r = L;
}
inline void init_que(){
init_ST();
M = 0;
for(int i = 1 ; i <= L ; ++i)
if(ind[i] < 0)
GetQue(i);
sort(now + 1 , now + M + 1);
}
inline void add(int x){
if(x <= 0)
return;
if(!times[x]++){
ans2[x] += lft;
++cnt;
}
}
inline void del(int x){
if(x <= 0)
return;
if(!--times[x]){
ans2[x] -= lft;
--cnt;
}
}
inline void work(){
lft = M;
int L = 1 , R = 0;
for(int i = 1 ; i <= M ; ++i , --lft){
while(R < now[i].r)
add(ind[sa[++R]]);
while(L > now[i].l)
add(ind[sa[--L]]);
while(R > now[i].r)
del(ind[sa[R--]]);
while(L < now[i].l)
del(ind[sa[L++]]);
ans1[now[i].ind] = cnt;
}
}
inline void output(){
for(int i = 1 ; i <= M ; ++i)
cout << ans1[i] << '\n';
for(int i = 1 ; i <= N ; ++i)
cout << ans2[i] << ' ';
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
init_SA();
init_que();
work();
output();
return 0;
}
Luogu2336 SCOI2012 喵星球上的点名 SA、莫队的更多相关文章
- BZOJ2754 [SCOI2012]喵星球上的点名 SA+莫队+树状数组
题面 戳这里 题解 首先先把所有给出的姓名和询问全部接在一起,建出\(height\)数组. 某个串要包含整个询问串,其实就相当于某个串与询问串的\(lcp\)为询问串的长度. 而两个后缀\(Suff ...
- BZOJ2754: [SCOI2012]喵星球上的点名
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 680 Solved: 314[Submit][Sta ...
- BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1906 Solved: 839[Submit][St ...
- 洛咕 P2336 [SCOI2012]喵星球上的点名
洛咕 P2336 [SCOI2012]喵星球上的点名 先求出SA和height,一个点名串对应的就是一段区间,还有很多个点,就转化成了 有很多个区间,很多个点集,对每个区间计算和多少个点集有交,对每个 ...
- 【BZOJ2754】[SCOI2012]喵星球上的点名
[BZOJ2754][SCOI2012]喵星球上的点名 题面 bzoj 洛谷 题解 这题有各种神仙做法啊,什么暴力\(AC\)自动机.\(SAM\)等等五花八门 我这个蒟蒻在这里提供一种复杂度正确且常 ...
- BZOJ 2754: [SCOI2012]喵星球上的点名
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 649 Solved: 305[Submit][Sta ...
- BZOJ 2754: [SCOI2012]喵星球上的点名 [AC自动机+map+暴力]
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1902 Solved: 837[Submit][St ...
- P2336 [SCOI2012]喵星球上的点名(后缀自动机+莫队+dfs序)
P2336 [SCOI2012]喵星球上的点名 名字怎么存?显然是后缀自动机辣 询问点到多少个喵喵喵其实就是 查询后缀自动机上parent树的一个子树 于是我们考虑莫队 怎么树上莫队呢 我们用dfs序 ...
- 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告
P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...
随机推荐
- KVM虚拟化研究-1
使用qemu-img创建镜像 例子: [root@HOST31 rybtest]# qemu-img create -f raw /rybtest/test1.raw 1G 使用qemu-img查看镜 ...
- mysql从入门到放弃-入门知识介绍
数据库在互联网网站的重要性 简单地说,数据库就是一个存放数据的仓库,这个仓库是按照一定的数据结构来组织和存储的,我们可以通过数据库提供的多种方法来管理数据库里的数据.由于数据库不易扩展,所以,在一个互 ...
- 不要拿ERP的报表忽悠领导!——一个报表引发的企业经营反思
文 | 帆软数据应用研究院船长 本文出自:知乎专栏<帆软数据应用研究院>——数据干货&资讯集中地 领导的经营决策能只依赖于ERP报表吗? 不能! 1. ERP报表个性化不足:企业经 ...
- plsql如何导出查询结果
mark一下,感谢大牛分享:http://www.cnblogs.com/Marydon20170307/p/8385674.html
- 二. Redis 安全性
由于Redis速度相当快,当一台服务器比较好的时候,一个外部用户可以在一秒钟内进行150K(15万)次的密码尝试,因此意味着你需要设置一个非常非常强大的密码来防止暴力破解. 1.设置密码 (1). 通 ...
- 学习使用TestNG进行数据驱动测试
转自: https://mp.weixin.qq.com/s/8Bd8LEhiC2pu2VMcyNMGlQ 学习使用TestNG进行数据驱动测试 赵吃饭 51Testing软件测试网 前天 学习使 ...
- python第十九天——感冒中
ConfigParser模块,hashlib模块,hmac模块: 创建配置文件: import configparser config = configparser.ConfigParser()#创建 ...
- IP负载均衡
推荐一篇关于LVS的好文: https://www.cnblogs.com/gaoxu387/p/7941381.html 一.原博主要内容: 1.概述 IP负载均衡:四层负载,是基于IP+端口的负载 ...
- C#使用Aforge调用摄像头拍照
一. 新建一个Winform项目 二.使用Nuget添加引用 安装下图中红色框住的两个程序包 安装完后发现安装了如下图的程序包,这是因为上述两个程序包存在对其它程序包的依赖. 三.编写程序 1. 窗体 ...
- [MapReduce_8] MapReduce 中的自定义分区实现
0. 说明 设置分区数量 && 编写自定义分区代码 1. 设置分区数量 分区(Partition) 分区决定了指定的 Key 进入到哪个 Reduce 中 分区目的:把相同的 Key ...