所以,读题很关键!!!
有不会线段树的同学可以去自学一下QAQ。
Code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
inline int read(){
register int x=0,v=1,ch=getchar();
while(!isdigit(ch)){if(ch==‘-‘)v=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^‘0‘);ch=getchar();}
return x*v;
}
const int MAX=50005;
int n,m,op[MAX];
struct Node{
string s;
int p,t;//分别表示原来的位置和字典序排名
}a[MAX];
//两个cmp过程,第一个是获取字典序的排名,第二个是将序列还原
inline bool cmp(Node x,Node y){return x.s<y.s;}
inline bool comp(Node x,Node y){return x.p<y.p;}
int tree[MAX<<2];
inline int Max(int a,int b){
return a>b?a:b;
}
//以下至58行是线段树的过程
inline void pushup(int x){
tree[x]=Max(tree[x<<1],tree[x<<1|1]);
}
void build(int x,int l,int r){
if(l==r){
tree[x]=a[l].t;
return ;
}
register int mid=l+r>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
pushup(x);
}
int query(int x,int l,int r,int s,int t){
if(s<=l&&r<=t)return tree[x];
register int mid=l+r>>1,res=-0x7fffffff;
if(s<=mid)res=Max(res,query(x<<1,l,mid,s,t));
if(mid<t)res=Max(res,query(x<<1|1,mid+1,r,s,t));
return res;
}
int l,r;
string c[MAX];
int main(){
n=read();m=read();
for(register int i=1;i<=n;++i){
cin>>a[i].s;
c[i]=a[i].s;
a[i].p=i;
}
for(register int i=1;i<=n;++i){//字典序大小转换
for(register int j=0;j<a[i].s.length();++j){
if(‘a‘<=a[i].s[j]&&a[i].s[j]<=‘z‘)a[i].s[j]-=32;
}
}
sort(a+1,a+1+n,cmp);
for(register int i=1;i<=n;++i)a[i].t=i;
sort(a+1,a+1+n,comp);
for(register int i=1;i<=n;++i)op[a[i].t]=i,a[i].s=c[i];
//op将查询到的最大排名映射回原来的查询字符串,c用于将a的字符串还原
build(1,1,n);
while(m--){
l=read(),r=read();
printf("%s\n",a[op[query(1,1,n,l,r)]].s.c_str());//输出字符串
}
return 0;
}
原文:https://www.cnblogs.com/Lates/p/12270914.html