题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4453

这种问题...一般先把询问离线,排序;

区间对后缀排名的影响在于一些排名大而位置靠后的后缀可能因为区间右端点截掉了后面而排名变小;

考虑如何影响:如果 i < j

rk[i] > rk[j] ,那么字典序 i 一直大于 j

rk[i] < rk[j] ,那么如果右端点 R <= j + LCP(i,j),字典序 i > j,如果 R > j + LCP(i,j),字典序 i < j

而如果对询问区间按右端点排序,右端点就是递增的;

需要处理一下 i < j , rk[i] < rk[j] 的情况,由于每个 i 只考虑暂时大于它后面第一个 j (若还有 k,之后考虑 j 暂时大于 k),所以用单调栈找到后面第一个大于的;

有类似插入、删除这样的操作,可以用 set 维护,当 R > j + LCP 后,就把 i 删除;

令 set 里面是当前有贡献的位置,也就是单调栈里的位置和虽然被弹出但暂时大于后面某个后缀的位置;

然后在位置上开个 vector 记录到这个地方贡献就失效的后缀,到了后把它们再从 set 里删除;

因为 set 里位置的贡献也是从左到右单调递减的,那么每次取 L 右边第一个就是答案;

别写错ST表!

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
#define pb push_back
using namespace std;
int const xn=1e5+;
int n,m,tax[xn],tp[xn],sa[xn],rk[xn],sta[xn],top,dc[xn],ht[xn][],bin[],r[xn],ans[xn];
char s[xn];
vector<int>v[xn],com[xn];
set<int>st;
set<int>::iterator it;
struct N{int l,r,id;}q[xn];
bool cmp(N x,N y){return x.r<y.r;}
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
void Rsort()
{
for(int i=;i<=m;i++)tax[i]=;
for(int i=;i<=n;i++)tax[rk[tp[i]]]++;
for(int i=;i<=m;i++)tax[i]+=tax[i-];
for(int i=n;i;i--)sa[tax[rk[tp[i]]]--]=tp[i];
}
void work()
{
for(int i=;i<=n;i++)rk[i]=s[i],tp[i]=i;
Rsort();
for(int k=;k<=n;k<<=)
{
int num=;
for(int i=n-k+;i<=n;i++)tp[++num]=i;
for(int i=;i<=n;i++)
if(sa[i]>k)tp[++num]=sa[i]-k;
Rsort(); swap(rk,tp);
rk[sa[]]=; num=;
for(int i=;i<=n;i++)
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-]]&&tp[sa[i]+k]==tp[sa[i-]+k])?num:++num;
if(num==n)break;
m=num;
}
}
void get()
{
int k=;
for(int i=;i<=n;i++)
{
if(rk[i]==)continue;
if(k)k--; int j=sa[rk[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
ht[rk[i]][]=k;
}
bin[]=; for(int i=;i<;i++)bin[i]=(bin[i-]<<);
r[]=; for(int i=;i<=n;i++)r[i]=r[i>>]+;
for(int j=;j<;j++)
for(int i=;i<=n&&i+bin[j]-<=n;i++)
ht[i][j]=min(ht[i][j-],ht[i+bin[j-]][j-]);//
}
int getlcp(int x,int y)
{
if(x==y)return n;
x=rk[x]; y=rk[y];
if(x>y)swap(x,y); x++;
int w=r[y-x+];
return min(ht[x][w],ht[y-bin[w]+][w]);//
}
int main()
{
scanf("%s",s+); n=strlen(s+);
for(int i=;i<=n;i++)dc[i]=(int)s[i];
sort(dc+,dc+n+); m=unique(dc+,dc+n+)-dc-;
for(int i=;i<=n;i++)s[i]=lower_bound(dc+,dc+m+,(int)s[i])-dc;
work(); get();
int Q=rd();
for(int i=;i<=Q;i++)q[i].l=rd(),q[i].r=rd(),q[i].id=i;
sort(q+,q+Q+,cmp); int p=;
for(int i=;i<=Q;i++)
{
while(p<q[i].r)
{
p++; int y;
while(rk[y=sta[top]]<rk[p]&&top)//<
{
int pos=min(n+,p+getlcp(y,p));
v[pos].pb(y); com[p].pb(y);
top--;
}
sta[++top]=p; st.insert(p);
for(int i=,x;i<v[p].size();i++)
if(st.count(x=v[p][i]))
{
for(int j=;j<com[x].size();j++)
if(st.count(com[x][j]))st.erase(com[x][j]);
st.erase(x);
}
}
it=st.lower_bound(q[i].l);
ans[q[i].id]=*it;
}
for(int i=;i<=Q;i++)printf("%d\n",ans[i]);
return ;
}

bzoj 4453 cys就是要拿英魂! —— 后缀数组+单调栈+set的更多相关文章

  1. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

  2. 【BZOJ-3238】差异 后缀数组 + 单调栈

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1561  Solved: 734[Submit][Status] ...

  3. BZOJ_3879_SvT_后缀数组+单调栈

    BZOJ_3879_SvT_后缀数组+单调栈 Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个 ...

  4. BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈

    BZOJ_3238_[Ahoi2013]差异_后缀数组+单调栈 Description Input 一行,一个字符串S Output 一行,一个整数,表示所求值 Sample Input cacao ...

  5. 【BZOJ3879】SvT 后缀数组+单调栈

    [BZOJ3879]SvT Description (我并不想告诉你题目名字是什么鬼) 有一个长度为n的仅包含小写字母的字符串S,下标范围为[1,n]. 现在有若干组询问,对于每一个询问,我们给出若干 ...

  6. BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】

    题目链接 BZOJ3238 题解 简单题 经典后缀数组 + 单调栈套路,求所有后缀\(lcp\) #include<iostream> #include<cstdio> #in ...

  7. BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]

    4453: cys就是要拿英魂! Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 46[Submit][Status][Discu ...

  8. BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】

    题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...

  9. BZOJ.4453.cys就是要拿英魂!(后缀数组 单调栈)

    BZOJ 求字典序最大,容易想到对原串建后缀数组求\(rk\). 假设当前区间是\([l,r]\),对于在\([l,r]\)中的两个后缀\(i,j\)(\(i<j\)),显然我们不能直接比较\( ...

随机推荐

  1. Windows 10 1703创意者更新官方ISO镜像大全

    2017年04月07日 20:00 19867 次阅读 稿源:快科技 12 条评论 Windows 10 Creators Update创意者更新正式版已经发布,目前只能通过易生.MCT工具或者ISO ...

  2. 07 redi sorder set结构及命令详解

    zadd key score1 value1 score2 value2 .. 添加元素 redis 127.0.0.1:6379> zadd stu 18 lily 19 hmm 20 lil ...

  3. 【转】win7 任务计划 任务映像已损坏或篡改(异常来自HRESULT:0x80041321)

    请这样操作:1. 以管理员身份运行命令提示符并执行命令chcp 437schtasks /query /v | find /i "ERROR: Task cannot be loaded:& ...

  4. Angular1.0路由的Hashbang和HTML5模式

    原文答主jupiter http://stackoverflow.com/questions/16677528/location-switching-between-html5-and-hashban ...

  5. iOSPOI检索详细总结

    iOS百度地图路径规划和POI检索详细总结 路径规划.png 百度地图的使用 百度地图API的导入网上说了许多坑,不过我遇到的比较少,这里就放两个比较常见的吧.坑一: 奥联WIFI_xcodeproj ...

  6. PDO:: 数据访问抽象层 ? :

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. TP框架---thinkphp查询和添加数据

    查询 <?php namespace Admin\Controller; use Think\Controller; class MainController extends Controlle ...

  8. 【BZOJ4173】数学 欧拉函数神题

    [BZOJ4173]数学 Description Input 输入文件的第一行输入两个正整数 . Output 如题 Sample Input 5 6 Sample Output 240 HINT N ...

  9. 【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree

    [BZOJ4605]崂山白花蛇草水 Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了 ...

  10. 九度OJ 1168:字符串的查找删除 (查找)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4276 解决:1699 题目描述: 给定一个短字符串(不含空格),再给定若干字符串,在这些字符串中删除所含有的短字符串. 输入: 输入只有1 ...