一、题意
给n个数,m个询问,每次询问,求L,R内内围成三角形的最大周长。
二、思路
我们知道,三角形三条边a,b,c应当满足a+b>c。则我们采用主席树,不断地求第1大、第二大、第K大的数判断是否满足条件即可。事实上,只要区间够大,解一定存在。三角形其本质类似斐波那契数列,所以最多约进行50项左右就可以停下来。
三、Code
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn = 1e5;
void work();
int tot, n, m;
int sum[maxn*40], rt[maxn*40], ls[maxn*40],
rs[maxn*40];
int a[maxn + 10], ind[maxn + 10], len;
inline int getid(const int &val)
{
return lower_bound(ind + 1, ind + len + 1, val) - ind;
}
int build(int l, int r)
{
int root = ++tot;
if (l == r) return root;
int mid = l + r >> 1;
ls[root] = build(l, mid);
rs[root] = build(mid + 1, r);
return root;
}
int update(int k, int l, int r, int root)
{
int dir = ++tot;
ls[dir] = ls[root], rs[dir] = rs[root], sum[dir] = sum[root] + 1;
if (l == r) return dir;
int mid = l + r >> 1;
if (k <= mid)
ls[dir] = update(k, l, mid, ls[dir]);
else
rs[dir] = update(k, mid + 1, r, rs[dir]);
return dir;
}
int query(int u, int v, int l, int r, int k)
{
int mid = l + r >> 1,
x = sum[ls[v]] - sum[ls[u]];
if (l == r) return l;
if (k <= x)
return query(ls[u], ls[v], l, mid, k);
else
return query(rs[u], rs[v], mid + 1, r, k - x);
}
inline void init() {
while(~scanf("%d%d", &n, &m)){
tot=0;
memset(sum,0,sizeof sum);
memset(rt,0,sizeof rt);
memset(ls,0,sizeof ls);
memset(rs,0,sizeof rs);
memset(ind,0,sizeof ind);
for (register int i = 1; i <= n; ++i) scanf("%d", a + i);
memcpy(ind, a, sizeof ind);
sort(ind + 1, ind + n + 1);
len = unique(ind + 1, ind + n + 1) - ind - 1;
rt[0] = build(1, len);
for (register int i = 1; i <= n; ++i)
rt[i] = update(getid(a[i]), 1, len, rt[i - 1]);
work();
}
}
int l, r, k;
ll numm[maxn+5];
inline void work() {
while (m--) {
scanf("%d%d", &l, &r);
k=r-l+1;
if(k<=2){
puts("-1");
}else{
int D=3;
ll a=1ll*ind[query(rt[l - 1], rt[r], 1, len, k)];
ll b=1ll*ind[query(rt[l - 1], rt[r], 1, len, k-1)];
ll c=1ll*ind[query(rt[l - 1], rt[r], 1, len, k-2)];
// cout<<a<<' '<<b<<' '<<c<<endl;
// cout<<1ll*ind[query(rt[l - 1], rt[r], 1, len, 0)]<<endl;
ll ans=-1;
while(D<k&&b+c<=a){
a=b;
b=c;
c=1ll*ind[query(rt[l - 1], rt[r], 1, len, k-D)];
D++;
}
// cout<<a<<' '<<b<<' '<<c<<endl;
if(b+c>a) ans=a+b+c;
printf("%lld\n",ans);
// printf("%d\n", ind[query(rt[l - 1], rt[r], 1, len, k)]);
}
}
}
int main() {
init();
return 0;
}