luogu2336 喵星球上的点名 (SA+二分答案+树状数组)
离散化一下然后把姓名串和询问串都放一起做SA
和bzoj3277串类似地,满足某一询问的后缀(就是和这个询问对应的后缀的LCP>=这个询问长度的后缀)的排名也是一个区间,把这个区间二分出来即可
现在要做的两个问题就变成了:
给定一些区间、一些点,每个点有对应的颜色(就是sa[i]对应的那个姓名串对应的人),问
1.每个区间中不同颜色的数量:同HH的项链
2.每个颜色被不同区间覆盖的数量:
想法其实和1是类似的,扫到区间左端点的时候给a[i]++,扫到右端点的时候给a[对应左端点]--,然后每个点贡献的区间数就是pre[i]-pre[i的颜色上次出现位置],因为相当于我们每次算的是左端点在上次出现位置与现在位置之间的、右端点在现在位置之后的区间,是不重不漏的
(千万不要写出s[++j]=data[j]=rd();这种代码然后因为某些特性在某些地方A某些地方wa然后跑到讨论区去丢人)
#include<bits/stdc++.h>
#define pa pair<int,int>
#define ll long long
using namespace std;
const int maxn=4e5+,maxm=5e4+,maxq=1e5+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Node{
int l,r,i;
}que[maxq];
int NN,N,M,Q;
int data[maxn],s[maxn],bel[maxn];
int sa[maxn],rank[maxn],hei[maxn],rank1[maxn],tmp[maxn],cnt[maxn];
int st[maxn][],pos[maxq][];
int tr[maxn],L[maxn],lst[maxn],ans[maxq]; inline int lowbit(int x){return x&(-x);}
inline void add(int x,int y){
for(;x<=N;x+=lowbit(x)) tr[x]+=y;
}
inline int query(int x){
int re=;for(;x>;x-=lowbit(x)) re+=tr[x];return re;
} inline void getsa(){
int i,j=,k;
for(i=;i<=N;i++) cnt[s[i]]=;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) rank[i]=cnt[s[i]]; for(k=;j!=N;k<<=){
memset(cnt,,sizeof(cnt));
for(i=;i<=N;i++) cnt[rank[i+k>N?:i+k]]++;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) tmp[cnt[rank[i+k>N?:i+k]]--]=i;
memset(cnt,,sizeof(cnt));
for(i=;i<=N;i++) cnt[rank[i]]++;
for(i=;i<=M;i++) cnt[i]+=cnt[i-];
for(i=N;i;i--) sa[cnt[rank[tmp[i]]]--]=tmp[i];
memcpy(rank1,rank,sizeof(rank1));
rank[sa[]]=j=;
for(i=;i<=N;i++){
if(rank1[sa[i]]!=rank1[sa[i-]]||rank1[sa[i]+k>N?:sa[i]+k]!=rank1[sa[i-]+k>N?:sa[i-]+k]) j++;
rank[sa[i]]=j;
}M=j;
}
for(i=;i<=N;i++) sa[rank[i]]=i;
} inline void geth(){
for(int i=,j=;i<=N;i++){
if(rank[i]==) continue;
if(j) j--;
int x=sa[rank[i]-];
while(x+j<=N&&i+j<=N&&s[x+j]==s[i+j]) j++;
hei[rank[i]]=j;
}
} inline void getst(){
for(int i=N;i;i--){
st[i][]=hei[i];
for(int j=;st[i+(<<(j-))][j-];j++){
st[i][j]=min(st[i][j-],st[i+(<<(j-))][j-]);
}
}
} inline int rmq(int l,int r){
int x=log2(r-l+);
return min(st[l][x],st[r-(<<x)+][x]);
} inline void getq(int id,int p,int x){
int l0,r0,l,r;
if(hei[p+]<x) r0=p;
else{
l=p+,r=N;
while(l<=r){
int m=l+r>>;
if(rmq(p+,m)>=x) r0=m,l=m+;
else r=m-;
}
}
if(hei[p]<x) l0=p;
else{
l=,r=p;
while(l<=r){
int m=l+r>>;
if(rmq(m,p)>=x) l0=m-,r=m-;
else l=m+;
}
}
que[id].l=l0,que[id].r=r0,que[id].i=id;
} inline bool cmp(Node a,Node b){
return a.r<b.r;
} inline void solve(){
int i,j,k;
for(i=;i<=Q;i++){
getq(i,rank[pos[i][]],pos[i][]-pos[i][]+);
L[i]=que[i].l;
}sort(que+,que+Q+,cmp);
sort(L+,L+Q+); for(i=,j=;i<=N&&j<=Q;i++){
int x=bel[sa[i]];
if(x){
if(lst[x]) add(lst[x],-);
add(i,);lst[x]=i;
}
for(;que[j].r==i&&j<=Q;j++){
ans[que[j].i]=query(que[j].r)-query(que[j].l-);
}
}
for(i=;i<=Q;i++) printf("%d\n",ans[i]);
memset(ans,,sizeof(ans));
memset(lst,,sizeof(lst));
memset(tr,,sizeof(tr));
for(i=,j=,k=;i<=N;i++){
for(;j<=Q&&L[j]==i;j++) add(i,);
ans[bel[sa[i]]]+=query(i)-query(lst[bel[sa[i]]]);
lst[bel[sa[i]]]=i;
for(;k<=Q&&que[k].r==i;k++) add(que[k].l,-);
}for(i=;i<=NN;i++) printf("%d ",ans[i]);
} int main(){
//freopen("2336.in","r",stdin);
int i,j,k;
NN=N=rd(),Q=rd();
for(i=,j=;i<=N*+Q;i++){
int a=rd();
if(i>N*) pos[i-N*][]=j+,pos[i-N*][]=j+a;
for(k=;k<a;k++){
s[j]=data[++j]=rd();
if(i<=N*) bel[j]=(i+)/;
}
s[j]=data[++j]=-;
}N=j;
sort(data+,data+N+);
M=unique(data+,data+N+)-data-;
for(i=;i<=N;i++) s[i]=lower_bound(data+,data+M+,s[i])-data-;
M+=;
getsa();geth();getst();
solve();
return ;
}
luogu2336 喵星球上的点名 (SA+二分答案+树状数组)的更多相关文章
- BZOJ2754 [SCOI2012]喵星球上的点名 SA+莫队+树状数组
题面 戳这里 题解 首先先把所有给出的姓名和询问全部接在一起,建出\(height\)数组. 某个串要包含整个询问串,其实就相当于某个串与询问串的\(lcp\)为询问串的长度. 而两个后缀\(Suff ...
- BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)
吐槽: 为啥很多人用AC自动机暴力跳都过了?复杂度真的对么? 做法一: AC自动机+树状数组 姓名的问题,中间加个特殊字符连起来即可. 肯定是对点名串建AC自动机(map存儿子),然后第一问就相当于问 ...
- [CSP-S模拟测试]:序列(二分答案+树状数组)
题目传送门(内部题98) 输入格式 第一行一个整数$n$,第二行$n$个整数$a_1\sim a_n$,第三行$n$个整数$b_1\sim b_n$. 输出格式 一行一个整数表示$\max(r-l+1 ...
- cf1073D Berland Fair (二分答案+树状数组)
用一个树状数组维护前缀和,每次我二分地找一个位置,使得我能一路买过去 但这个买不了 那以后肯定也都买不了了,就把它改成0,再从头二分地找下一个位置,直到这一圈我可以跑下来 然后就看跑这一圈要花多少钱. ...
- AtCoder Regular Contest 101 (ARC101) D - Median of Medians 二分答案 树状数组
原文链接https://www.cnblogs.com/zhouzhendong/p/ARC101D.html 题目传送门 - ARC101D 题意 给定一个序列 A . 定义一个序列 A 的中位数为 ...
- 【序列莫队+二分答案+树状数组】POJ2104-K-th Number
[题目大意] 给出一个长度为n的序列和m组查询(i,j,k),输出[i,j]中的第k大数. [思路] 先离散化然后莫队分块.用树状数组来维护当前每个值的个数,然后对于每次询问二分答案即可. 又一次实力 ...
- 4418: [Shoi2013]扇形面积并|二分答案|树状数组
为何感觉SHOI的题好水. ..又是一道SB题 从左到右枚举每个区间,遇到一个扇形的左区间就+1.遇到右区间就-1,然后再树状数组上2分答案,还是不会码log的.. SHOI2013似乎另一道题发牌也 ...
- Luogu2336 SCOI2012 喵星球上的点名 SA、莫队
传送门 一道很套路的题目 先将所有串拼在一起,两个不同的串之间放一个没有出现在任何串中的字符做分隔,然后SA 那么对于所有点名串能够点到的名字串在SA中对应一段区间 把这些区间拿出来然后莫队统计每一个 ...
- 【BZOJ2754】[SCOI2012]喵星球上的点名
[BZOJ2754][SCOI2012]喵星球上的点名 题面 bzoj 洛谷 题解 这题有各种神仙做法啊,什么暴力\(AC\)自动机.\(SAM\)等等五花八门 我这个蒟蒻在这里提供一种复杂度正确且常 ...
随机推荐
- 使用TensorFlow的递归神经网络(LSTM)进行序列预测
本篇文章介绍使用TensorFlow的递归神经网络(LSTM)进行序列预测.作者在网上找到的使用LSTM模型的案例都是解决自然语言处理的问题,而没有一个是来预测连续值的. 所以呢,这里是基于历史观察数 ...
- CentOS 7 安装Redis
Linux安装Redis 一.下载并安装 $ wget http://download.redis.io/releases/redis-2.8.17.tar.gz $ tar xzf redis-2. ...
- subprocess.Popen指令包含中文导致乱码问题解决
其实解决起来非常简单,如果了解到Windows中文系统编码为GB2312的话 只需将你包含中文的指令字符串编码为GB2312即可 cmd = u'cd 我的文档' cmd.encode('gb2312 ...
- Ionic 2 官方示例程序 Super Starter
原文发表于我的技术博客 本文分享了 Ionic 2 官方示例程序 Super Starter 的简要介绍与安装运行的方法,最好的学习示例代码,项目共包含了 14 个通用的页面设计,如:引导页.主页面详 ...
- Nginx反向代理的简单实现
1)nginx的反向代理:proxy_pass2)nginx的负载均衡:upstream 下面是nginx的反向代理和负载均衡的实例: 负载机:A机器:103.110.186.8/192.168.1. ...
- 705 B. Spider Man
传送门 [http://codeforces.com/contest/705/problem/B] 题意 这题意看原文的真tm难懂Woc,但结合样例就知道大概意思了 两个轮流分环,可以这么理解两个人轮 ...
- mapreduce 中 map数量与文件大小的关系
学习mapreduce过程中, map第一个阶段是从hdfs 中获取文件的并进行切片,我自己在好奇map的启动的数量和文件的大小有什么关系,进过学习得知map的数量和文件切片的数量有关系,那文件的大小 ...
- atcoder B - Frog 2 (DP)
B - Frog 2 Time Limit: 2 sec / Memory Limit: 1024 MB Score : 100100 points Problem Statement There a ...
- Install alipay支付宝安全控件 on firefox in linux
[root@rgqancy 下载]# ./aliedit.sh建议以非root账号安装支付宝安全控件请重启 firefox 使插件生效成功安装 支付宝安全控件请按任意键退出... what i ...
- mysql 备份数据库 mysqldump
@echo off for /F "usebackq tokens=1,2 delims==" %%i in (`wmic os get LocalDateTime /VALUE ...