您的位置:首页 > 其它

【BZOJ4453】cys就是要拿英魂!

2016-04-01 15:08 162 查看
Description

pps又开始dota视频直播了!

一群每天被pps虐的蒟蒻决定学习pps的操作技术,他们把pps在这局放的技能记录了下来,每个技能用一个字符表示。经过研究,蒟蒻们发现字典序更大的连招威力更大。于是所有蒟蒻都想学习pps最强的连招。但是他们太弱了,不能学会整个视频里的连招,只能学会陈老师一段区间间内的连招,可是这个他们求不出,于是只好向你求助。为了蒟蒻们不再被pps虐(怎么可能),请你帮帮他们。

简化题意:

给你一个字符串,每次询问你一段区间的字典序最大的子串。

Input

第一行是一个字符串S,表示pps放的技能

第二行一个正整数Q,表示询问个数

接下来Q行,每行两个正整数[l,r],表示询问区间[l,r]中的字典序最大的子串。

Output

Q行,每行一个正整数,表示该区间内字典序最大的子串的起始位置。

Sample Input

Lets_go_mod_p!

5

2 2

3 3

2 5

1 10

2 9

Sample Output

2

3

3

3

3

数据范围:

1<=|S|<=100000

1<=Q<=100000

1<=l<=r<=|S|

HINT

Source

原题是neerc2012.

一开始一看..这个东西是不是叫区间border来着?border_tree?不会..pass掉..

后来一想..线段树套后缀平衡树?那是啥..问Claris..不可做..

最后发现..其实什么高级的科技都不需要..

zimpha在ICPCCAMP的官方论坛里给出了一个题解.

题目讨论

如果你打不开这个题解,我还有截图:



因为他写的非常详细,所以我也不细写了..

真的是非常好的思想和姿势,没有使用高端字符串数据结构就解决了这个题.

为什么qiancl大爷写什么题都跑的那么快…

他做过的题我从没有一个rank比他高..(砸

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#define MAXN 100010
#define base 55001
#define LL unsigned long long
#define GET (ch>='0'&&ch<='9')
using namespace std;
int n,Q,top1,top2,tp;
int ans[MAXN];
char ch[MAXN];
bool vis[MAXN];
LL hash[MAXN],Pow[MAXN];
int sta[MAXN];
struct query
{
int l,r,id;
inline bool operator <(const query& a)const {   return r==a.r?l<a.l:r<a.r;  }
}q[MAXN];
struct edge {   int to; edge *next; }e1[MAXN<<1],*prev1[MAXN],e2[MAXN<<1],*prev2[MAXN];
struct Edge {   int l,id;   Edge *next; }E[MAXN],*Prev[MAXN];
inline void insert1(int u,int v)    {   e1[++top1].to=v;e1[top1].next=prev1[u];prev1[u]=&e1[top1];  }
inline void insert2(int u,int v)    {   e2[++top2].to=v;e2[top2].next=prev2[u];prev2[u]=&e2[top2];  }
inline void add(int x,int l,int id) {   E[++tp].id=id;E[tp].l=l;E[tp].next=Prev[x];Prev[x]=&E[tp];  }
set<int> S;
inline void in(int &x)
{
char ch=getchar();x=0;
while (!GET)    ch=getchar();
while (GET) x=x*10+ch-'0',ch=getchar();
}
inline int lcp(int a,int b)
{
int l=1,r=n-max(a,b)+1,ret=0;
while (l<=r)
{
int mid=(l+r)>>1;
LL x=hash[a]-hash[a+mid]*Pow[mid],y=hash[b]-hash[b+mid]*Pow[mid];
if (x==y)   ret=mid,l=mid+1;    else    r=mid-1;
}
return ret;
}
void dfs(int x)
{
vis[x]=1;S.erase(x);
for (edge *i=prev2[x];i;i=i->next)  if (!vis[i->to])    dfs(i->to);
}
int main()
{
scanf("%s",ch+1);in(Q);n=strlen(ch+1);
Pow[0]=1;int l,r;
for (int i=1;i<=n;i++)  Pow[i]=Pow[i-1]*base;
for (int i=n;i;i--) hash[i]=hash[i+1]*base+ch[i];
for (int i=1;i<=Q;i++)  in(l),in(r),add(r,l,i);
for (int i=1;i<=n;i++)
{
S.insert(i);
while (sta[0])
{
int len=lcp(i,sta[sta[0]]);
if (ch[sta[sta[0]]+len]>ch[i+len])  break;
insert1(i+len,sta[sta[0]]);insert2(i,sta[sta[0]]);sta[0]--;
}
sta[++sta[0]]=i;
for (edge *j=prev1[i];j;j=j->next)  if (!vis[j->to])    dfs(j->to);
for (Edge *j=Prev[i];j;j=j->next)   ans[j->id]=*S.lower_bound(j->l);
}
for (int i=1;i<=Q;i++)  printf("%d\n",ans[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Hash border