每次询问一个区间,最多44次以内就能找到三角形(想想三角形性质,结合斐波那契数列在1e9取值)
每次先找前第3大的,然后一直往前找直到超出区间,这个过程用主席树维护。
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll ;
const int oo=0x7f7f7f7f ;
const int maxn=4e5+7;
const int mod=1e9+7;
int n,m,cnt,root[maxn],a[maxn],x,y,k;
struct node{
int l,r,sum;
}T[maxn*25];
vector<int> v;
int getid(int x){
return lower_bound(v.begin(),v.end(),x)-v.begin()+1;
}
void update(int l,int r,int &x,int y,int pos){
T[++cnt]=T[y],T[cnt].sum++,x=cnt;
if(l==r) return;
int mid=(l+r)/2;
if(mid>=pos) update(l,mid,T[x].l,T[y].l,pos);
else update(mid+1,r,T[x].r,T[y].r,pos);
}
int query(int l,int r,int x,int y,int k){
//printf("%d--%d\n",l,r);
if(l==r) return l;
int mid=(l+r)/2;
int sum=T[T[y].l].sum-T[T[x].l].sum;
if(sum>=k) return query(l,mid,T[x].l,T[y].l,k);
else return query(mid+1,r,T[x].r,T[y].r,k-sum);
}
int main(void){
while(~scanf("%d%d",&n,&m))
{
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++) update(1,n,root[i],root[i-1],getid(a[i]));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
// puts("ook") ;
int len=y-x+1;
if(len<3)
{
puts("-1");
continue;
}
ll ans=0;
ll a[4];
bool flag=false;
for(int j=len;j>=len-2;j--)
{
// puts("ok");
a[len-j+1]=(ll)v[query(1,n,root[x-1],root[y],j)-1];
ans+=a[j];
// cout<<a[i]<<"--"<<endl;
// cout<<ans<<"---"<<x<<"->"<<y<<endl;
}
sort(a+1,a+4);
if(a[1]+a[2]>a[3])
flag=true;
else
{
for(int j=len-3;j>=1;j--)
{
ans-=a[3];
a[3]=(ll)v[query(1,n,root[x-1],root[y],j)-1];
ans+=a[3];
sort(a+1,a+4);
if(a[1]+a[2]>a[3])
{
flag=true;
break;
}
}
}
if(flag)
printf("%lld\n",a[1]+a[2]+a[3]);
else
printf("-1\n");
}
for(int i=1;i<=n;i++)
root[i]=0;
for(int i=1;i<=25*n;i++)
T[i].l=0,T[i].r=0,T[i].sum=0;
}
return 0;
}
/*
10 4
1000 100 10 1 13 23 33 45 100000 200000
1 4
2 5
1 6
6 10
*/