找区间内三条边可组成周长最长的三角形,因为三角形边长关系,最坏情况就是斐波那契数,从1e9按斐波那契数递减,题解上说就44个,所以就暴力找区间内第k,k-1,k-2大数,判断其是否组成三角形
保险开个long long ,根据hdu2665模板写的,那题题意真的问题很大,让我以为模板是找第k大的数,结果却是找第k小的,模板还要稍微改一下,特判当所给区间长度没有三直接输出负一,这里卡了一个小时
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<ctime>
#include<algorithm>
#define eps 1e-14
#define pi acos(-1)
#define ll long long
#define RD T*(rand()*2-RAND_MAX)
#define Drand (long double)rand()/RAND_MAX
#define LINF 1e18
#define INF 0x3f3f3f3f
using namespace std;
const int maxn=1e5+10;
const int mod=1e4+7;
int tot=0;
int aa[maxn],a[maxn],L[maxn*21],R[maxn*21],sum[maxn*21],T[maxn];
void build(int l,int r,int &rt)
{
rt=++tot;
sum[rt]=0;
if(l==r)return;
int mid=(l+r)>>1;
build(l,mid,L[rt]);
build(mid+1,r,R[rt]);
}
void update(int l,int r,int &rt,int pre,int x)
{
rt=++tot;
L[rt]=L[pre];
R[rt]=R[pre];
sum[rt]=sum[pre]+1;
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)update(l,mid,L[rt],L[pre],x);
else update(mid+1,r,R[rt],R[pre],x);
}
int query(int l,int r,int tl,int tr,int k)
{
if(l==r)return l;
int mid=(l+r)>>1;
int res=sum[ R[tr] ] - sum[ R[tl] ];
if(res>=k)query(mid+1,r,R[tl],R[tr],k);
else query(l,mid,L[tl],L[tr],k-res);
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;i++)scanf("%d",&aa[i]),a[i]=aa[i];
sort(a+1,a+1+n);
int num=unique(a+1,a+1+n)-a-1;
tot=0;
build(1,num,T[0]);
for(int i=1;i<=n;i++){
int x=lower_bound(a+1,a+1+num,aa[i])-a;
update(1,num,T[i],T[i-1],x);
}
while(m--){
int l,r;
scanf("%d%d",&l,&r);
if(r-l+1<3){
printf("-1\n");
continue;
}
int k=4,x1,x2,x3;
ll Max=-1;
x1=query(1,num,T[l-1],T[r],1);
x2=query(1,num,T[l-1],T[r],2);
x3=query(1,num,T[l-1],T[r],3);
if((ll)a[x1]<(ll)(a[x2]+a[x3]))Max=(ll)a[x1]+(ll)a[x2]+(ll)a[x3];
else{
while(k<=r-l+1){
x1=x2;
x2=x3;
x3=query(1,num,T[l-1],T[r],k);
if((ll)a[x1]<(ll)(a[x2]+a[x3])){
Max=(ll)a[x1]+(ll)a[x2]+(ll)a[x3];
break;
}
k++;
}
}
printf("%lld\n",Max);
}
}
return 0;
}