洛谷 P2412 查单词

题目背景

滚粗了的HansBug在收拾旧英语书,然而他发现了什么奇妙的东西。

题目描述

udp2.T3如果遇到相同的字符串,输出后面的

蒟蒻HansBug在一本英语书里面找到了一个单词表,包含N个单词(每个单词内包含大小写字母)。现在他想要找出某一段连续的单词内字典序最大的单词。

输入输出格式

输入格式:

第一行包含两个正整数N、M,分别表示单词个数和询问个数。

接下来N行每行包含一个字符串,仅包含大小写字母,长度不超过15,表示一个单词。

再接下来M行每行包含两个整数x、y,表示求从第x到第y个单词中字典序最大的单词。

输出格式:

输出包含M行,每行为一个字符串,分别依次对应前面M个询问的结果。

输入输出样例

输入样例#1: 
5 5
absi
hansbug
lzn
kkk
yyy
1 5
1 1
1 2
2 3
4 4
输出样例#1: 
yyy
absi
hansbug
lzn
kkk

说明

样例说明:

第一次操作:在{absi,hansbug,lzn,kkk,yyy}中找出字典序最大的,故为yyy

第二次操作:在{absi}中找出字典序最大的,故为absi

第三次操作:在{absi,hansbug}中找出字典序最大的,故为hansbug

第四次操作:在{hansbug,lzn}中找出字典序最大的,故为lzn

第五次操作:在{kkk}中找出字典序最大的,故为kkk

数据规模:

注意事项:1.该题目单词字典序比对过程中大小写不敏感,但是输出必须输出原单词

2.该题目时间限制为0.2s

 ST表 

题目链接

#include <cstring>
#include <cctype>
#include <cstdio>
#include <cmath>
#define N 50005

int n,m,len[N],maxn[N][20];
char word[N][15];
int max(int a,int b) {return a>b?a:b;}
int Max(int a,int b)
{
    for(int i=0;i<max(len[a],len[b]);++i)
    {
        char A=word[a][i],B=word[b][i];
        A=toupper(A);B=toupper(B);
        if(A==B) continue;
        if(A>B) return a;
        else return b;
    }
    return max(a,b);
}
void init()
{
    for(int i=1;i<=n;++i) maxn[i][0]=i;
    for(int j=1;j<=20;++j)
     for(int i=1;i<=n;++i)
         if(i+(1<<j)-1<=n) maxn[i][j]=Max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]);
}
inline int rmq(int l,int r)
{
    int logn=(int)(log((double)(r-l+1))/log(2.0));
    return Max(maxn[l][logn],maxn[r-(1<<logn)+1][logn]);
}
int main(int argc,char *argv[])
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) scanf("%s",word[i]),len[i]=strlen(word[i]);
    init();
    for(int l,r;m--;)
    {
        scanf("%d%d",&l,&r);
        puts(word[rmq(l,r)]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sy1in/p/7859311.html