谁是天才(续)

来源:互联网 发布:cheat engine 6.3 mac 编辑:程序博客网 时间:2024/04/30 00:29

Description

张大牛:“我是天才!”
大肥熊:“你为什么是天才?”
张大牛:“你随便给我一个单词(大小写字母组成)长度为N,去掉M个字符后,我能知道字典序最小的字符串是什么样子的”
大肥熊:“换过来,现在假设这个字典序最小的字符串中第ai个字符在原串中的位置为pos,那么原串中区间[pos-ki,pos+ki]中字典序最大的字符是什么?”
张大牛又被难倒了。现在这个难倒天才的题目交到你手上了。

注:区间[ pos-ki , pos+ki ]超过原字符串的边界,按照原字符串的边界处理。原串的整个区间为[1,N],如果pos可以取多个值,按照最靠前的位置计算。

Input

输入文件名为(genius.in)。
第一行M,T。M如题意,T为T组询问。
第二行为一个由大、小写字母组成的字符串。串的长度N(N>M>0)。
接下来T行每行两个正整数ai,ki(1<=ai<=N-M),(1<=ki<=N)。

Output

输出文件名为(genius.out)。
T行,每行对询问给出一个答案。

Sample Input

20 2abcdefghijklmnopqrstuvwxyz5 203 3

Sample Output

yf

Hint

对于100%数据,N<=10^5   T<=10^5

Key To Problem

乍一看,貌似是RMQ的题,但是RMQ是什么我不会写啊!所以我用的线段树水过。
维护区间最大和区间最小两个线段树,用区间最小的线段树来求字典序最小的子串,记录子串在字符串中的位置,之后对于每个查询就可以用区间最大的线段树搞出来。

Code

#include<cstdio>#include<cstring>#include<cstdlib>#include<iostream>#include<algorithm>#define N 100010#define ls rt<<1#define rs rt<<1|1#define lson l,mid,ls#define rson mid+1,r,rsusing namespace std;struct node{    int s,x;};node mx[N<<2],mn[N<<2];int n,m,q;char s[N];int a[N];int f[N];void PushUp(int rt){    if(mx[ls].s>=mx[rs].s)        mx[rt]=mx[ls];    else        mx[rt]=mx[rs];    if(mn[ls].s<=mn[rs].s)        mn[rt]=mn[ls];    else        mn[rt]=mn[rs];}void build(int l,int r,int rt){    if(l==r)    {        mn[rt].s=mx[rt].s=a[l];        mn[rt].x=mx[rt].x=l;        return ;    }    int mid=(l+r)>>1;    build(lson);    build(rson);    PushUp(rt);}node query_mx(int L,int R,int l,int r,int rt){    if(l>=L&&r<=R)        return mx[rt];    int mid=(l+r)>>1;    node a,b,s;    if(mid>=L)        a=query_mx(L,R,lson);    if(mid<R)        b=query_mx(L,R,rson);    if(mid<L)        return b;    if(mid>=R)        return a;    if(a.s>=b.s)        s=a;    else        s=b;    return s;}node query_mn(int L,int R,int l,int r,int rt){    if(l>=L&&r<=R)        return mn[rt];    int mid=(l+r)>>1;    node a,b,s;    if(mid>=L)        a=query_mn(L,R,lson);    if(mid<R)        b=query_mn(L,R,rson);    if(mid<L)        return b;    if(mid>=R)        return a;    if(a.s<=b.s)        s=a;    else        s=b;    return s;}int main(){//  freopen("genius.in","r",stdin);//  freopen("genius.out","w",stdout);    scanf("%d%d%s",&m,&q,s+1);    n=strlen(s+1);    m=n-m;    for(int i=1;i<=n;i++)    {        if(s[i]>='A'&&s[i]<='Z')            a[i]=s[i]-'A'+1;        else            a[i]=s[i]-'a'+27;    }    build(1,n,1);    int t=n-m,s=1,al=0;    while(++t&&al<m)    {        node x=query_mn(s,t,1,n,1);        f[++al]=x.x;        s=x.x+1;    }    for(int i=1;i<=q;i++)    {        int x,y;        scanf("%d%d",&x,&y);        int l=max(f[x]-y,1);        int r=min(f[x]+y,n);        int z=query_mx(l,r,1,n,1).s;        if(z<=26)            printf("%c\n",z-1+'A');        else            printf("%c\n",z-27+'a');    }    return 0;}
0 0