【BZOJ4453】cys就是要拿英魂! 后缀数组+单调栈+set
【BZOJ4453】cys就是要拿英魂!
Description
Input
Output
Sample Input
5
2 2
3 3
2 5
1 10
2 9
Sample Output
3
3
3
3
数据范围:
1<=|S|<=100000
1<=Q<=100000
1<=l<=r<=|S|
题解:看到题,想都不用想一定是后缀数组+离线乱搞。然后就越搞越复杂。这里还是直接贴正解好了。
注释:
这里实际上是用单调栈优化set,不要搞反。
标算的核心就是那个删除时刻的标记,还有那个“伴随”概念。更具体的做法是,我们对于每个点维护两套边,一套指向的是:有哪些点的删除标记是当前点,另一套指向的是:有哪些点伴随当前点。(形成了一个类似森林的结构?)这样,我们枚举那些删除树上的点,再DFS下去,删除所有伴随树上的点就行了。
后缀数组的LCP不要写错啊啊啊~调了好久。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
const int maxn=100010;
int n,m,top,cnt;
int ra[maxn],rb[maxn],st[maxn],r[maxn],sa[maxn],rank[maxn],h[maxn],f[maxn][20],sta[maxn];
int Log[maxn],ans[maxn],to[maxn<<1],next[maxn<<1],hb[maxn],hd[maxn],del[maxn];
char str[maxn];
set<int> s;
struct QUERY
{
int ql,qr,org;
}q[maxn];
int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
bool cmp(QUERY a,QUERY b)
{
return a.qr<b.qr;
}
void build()
{
n++;
int i,j,k,p,*x=ra,*y=rb;
for(i=0;i<n;i++) st[x[i]=r[i]]++;
for(i=1;i<m;i++) st[i]+=st[i-1];
for(i=n-1;i>=0;i--) sa[--st[x[i]]]=i;
for(j=p=1;p<n;m=p,j<<=1)
{
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<m;i++) st[i]=0;
for(i=0;i<n;i++) st[x[y[i]]]++;
for(i=1;i<m;i++) st[i]+=st[i-1];
for(i=n-1;i>=0;i--) sa[--st[x[y[i]]]]=y[i];
for(swap(x,y),x[sa[0]]=0,i=p=1;i<n;i++)
x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j])?p-1:p++;
}
for(i=1;i<n;i++) rank[sa[i]]=i;
for(i=k=0;i<n-1;h[rank[i++]]=k)
for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
n--;
for(i=1;i<=n;i++) f[i][0]=h[i];
for(i=2;i<=n;i++) Log[i]=Log[i>>1]+1;
for(j=1;(1<<j)<=n;j++) for(i=1;i+(1<<j)-1<=n;i++) f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
int getlcp(int a,int b)
{
a=rank[a],b=rank[b];
if(a>b) swap(a,b);
a++;
int k=Log[b-a+1];
return min(f[a][k],f[b-(1<<k)+1][k]);
}
void add(int c,int a,int b)
{
if(a>=n) return ;
to[cnt]=b;
if(c) next[cnt]=hb[a],hb[a]=cnt++;
else next[cnt]=hd[a],hd[a]=cnt++;
}
void dfs(int x)
{
del[x]=1,s.erase(x);
for(int i=hb[x];i!=-1;i=next[i]) if(!del[to[i]]) dfs(to[i]);
}
void ins(int x)
{
int i;
while(top)
{
if(rank[sta[top]]<rank[x]) add(0,x+getlcp(sta[top],x),sta[top]),add(1,x,sta[top]),top--;
else break;
}
sta[++top]=x,s.insert(x);
for(i=hd[x];i!=-1;i=next[i]) if(!del[to[i]]) dfs(to[i]);
}
int main()
{
memset(hb,-1,sizeof(hb));
memset(hd,-1,sizeof(hd));
scanf("%s",str),n=strlen(str);
int i,j;
for(i=0;i<n;i++) r[i]=str[i],m=max(m,r[i]+1);
build();
m=rd();
for(i=1;i<=m;i++) q[i].ql=rd()-1,q[i].qr=rd()-1,q[i].org=i;
sort(q+1,q+m+1,cmp);
for(i=1,j=0;i<=m;i++)
{
for(;q[i].qr>=j;j++) ins(j);
ans[q[i].org]=*(s.lower_bound(q[i].ql));
}
for(i=1;i<=m;i++) printf("%d\n",ans[i]+1);
return 0;
}
【BZOJ4453】cys就是要拿英魂! 后缀数组+单调栈+set的更多相关文章
- 【BZOJ-3238】差异 后缀数组 + 单调栈
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1561 Solved: 734[Submit][Status] ...
- BZOJ_3879_SvT_后缀数组+单调栈
BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...
- BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈
BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...
- BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)
BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...
- 【BZOJ3879】SvT 后缀数组+单调栈
[BZOJ3879]SvT Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干 ...
- BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】
题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...
- BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】
题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...
- BZOJ.4453.cys就是要拿英魂!(后缀数组 单调栈)
BZOJ 求字典序最大,容易想到对原串建后缀数组求\(rk\). 假设当前区间是\([l,r]\),对于在\([l,r]\)中的两个后缀\(i,j\)(\(i<j\)),显然我们不能直接比较\( ...
- BZOJ 4453 cys就是要拿英魂!(后缀数组+单调栈+平衡树)
一开始的时候感觉就是一个主席树裸题. 然后发现自己错了. 首先建出后缀数组. 设\(i<j\) 如果\(rk[i]>rk[j]\)显然i更优. 如果\(rk[i]<rk[j]\)不一 ...
随机推荐
- 误加all_load引起的程序报错
一.为什么要加-all_load 在64位的mac系统和iOS系统下,链接器有一个bug,会导致只包含有类别的静态库无法使用-ObjC标志来加载文件.解决方法是使用-all_load或者-force_ ...
- BZOJ 4543 2016北京集训测试赛(二)Problem B: thr 既 长链剖分学习笔记
Solution 这题的解法很妙啊... 考虑这三个点可能的形态: 令它们的重心为距离到这三个点都相同的节点, 则其中两个点分别在重心的两棵子树中, 且到重心的距离相等; 第三个点可能在重心的一棵不同 ...
- Jenkins introduction
http://birdinroom.blog.51cto.com/7740375/1342897 https://www.ibm.com/developerworks/cn/java/j-lo-jen ...
- iOS进行单元测试OCUnit+xctool
单元测试 什么是单元测试 wiki解释 简单说来就是为你的方法多专门写一个测试函数.以保证你的方法在不停的修改开发中.保持正确.如果出错,第一时间让你知道,这样从最小单位开始监控来保证软件的质量. 我 ...
- 一种全新的自动调用ajax方法
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- VS2010中 打开vc6.0的工程时,遇到的问题及解决办法
用VS2010打开vc6.0的工程时,遇到了很多的问题,下面记录下解决办法. 1. 报错: error C2065: “i”: 未声明的标识符 解决办法: 提出 i 的申明,因为 i 的申明可能在fo ...
- MySQL---SQL记录
MySQL在已有字段后追加相应的值值 需求:在MySQL中的topic表中,需要将每一个cover字段后添加上: -400.webp update topic set cover = CONCAT(c ...
- Ajax学习(一)——与Ajax的初次相识
AJAX是"Asynchronous Javascript And XML"的缩写,从字面上解释是"异步JavaScript和XML"的简称. 它不是一 ...
- vue 父子通信过程
1.概述 每个 Vue 实例都实现了事件接口,即: 使用 $on(eventName) 监听事件 使用 $emit(eventName, optionalPayload) 触发事件 2.示例一(未传递 ...
- LeetCode Subsets I& II——递归
I Given a set of distinct integers, S, return all possible subsets. Note: Elements in a subset must ...