#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int M=50;
int top,st,rnk[M+10];
int a[maxn];
vector<int>v;
inline int getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
struct Node{
int l,r,sum;
}hjt[maxn*40];
int cnt,root[maxn];
void insert(int l,int r,int pre,int &now,int p){
hjt[++cnt]=hjt[pre];
now=cnt;
hjt[now].sum++;
if(l==r) return;
int m=l+r>>1;
if(p<=m) insert(l,m,hjt[pre].l,hjt[now].l,p);
else insert(m+1,r,hjt[pre].r,hjt[now].r,p);
}
// int query(int l,int r,int L,int R,int k){//查找区间第k大
// if(l==r) return l;
// int m=l+r>>1;
// int tmp=hjt[hjt[R].r].sum-hjt[hjt[L].r].sum;
// if(k<=tmp) return query(m+1,r,hjt[L].r,hjt[R].r,k);
// else return query(l,m,hjt[L].l,hjt[R].l,k-tmp);
// }
void query(int l,int r,int L,int R){//一次询问处理好区间前44大
if(hjt[R].sum-hjt[L].sum==0||top==M) return;
if(l==r){
for(int i=0;i<hjt[R].sum-hjt[L].sum;++i)
if(top<M) rnk[top++]=v[l-1];//top++ l-1
return;
}
int m=l+r>>1;
query(m+1,r,hjt[L].r,hjt[R].r);
query(l,m,hjt[L].l,hjt[R].l);
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
cnt=0;//
v.clear();//
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
v.push_back(a[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1;i<=n;++i){
root[i]=0;//
insert(1,n,root[i-1],root[i],getid(a[i]));
}
while(m--){
int l,r,k;
scanf("%d%d",&l,&r);
top=0;
query(1,n,root[l-1],root[r]);
ll res=-1;
for(int i=2;i<top;++i){//i<45&&i<=r-l+1 -> i<top top++ 2-> i-2 i-1 i
if(rnk[i-2]<rnk[i-1]+rnk[i]){
res=rnk[i-2]+0ll+rnk[i-1]+rnk[i];
break;
}
}
printf("%lld\n",res);
}
}
return 0;
}
注意:
1. 后面加斜杠的三句话是初始化,不初始化的话答案不会错,但是会超时,主要是vector没清空,二分查找耗时,root[i]=0这句加不加无所谓(经分析并验证)。
2. 这题是一次询问就处理好区间前44大,不是遍历区间的时候挨个去查第1大、第2大......,会超时。
3. ll res=-1; 把答案赋给res时,要加一个0ll,否则会WA。直接输出 printf ( "%lld", rnk[i-2] + rnk[i-1] + rnk[i] ),就没有问题。
4. 注意各种下标、边界,仔细写。