题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6601

题目大意:
给你一个长度为nn的序列,有q个询问,每个询问给你一个区间[l,r],每次询问问你在区间[l,r]中,能够组成的最大的三角形的周长。

思路:
因为三角形具有两边之和大于第三边的性质,即a+b>c的性质。而倘若有若干个数都符合条件,则倘若我们将不等号改成等号,这就形成了一个斐波那契数列。而根据斐波那契数列的性质,值域在[1,a]的斐波那契数列最多会有log2(a)项。
而在这里可以利用这个性质,每个询问我们贪心的去取第k大、第k+1大、第k+3大的数进行比较,如果不符合条件则继续向后找第k+4项直到找到答案为止。因为值域上限为10^9故最大只需要枚举大概44。而每次寻找第k大,我们可以用主席树在O(logn)的时间复杂度下进行查询第kk大。故整体的时间复杂度为:O(44qlogn)

#include<bits/stdc++.h>

#define LL long long
using namespace std;
const int maxn=2e5+10;

LL L[maxn*20], R[maxn*20], sum[maxn*20];
LL n, q, m ,cnt = 0;
LL a[maxn], b[maxn], root[maxn];

#define mid (l+r)/2
LL JS(LL l, LL r)
{
    LL rt=++cnt;
    sum[rt]=0;
    if(l<r)
    {
        L[rt]=JS(l ,mid);
        R[rt]=JS(mid+1, r);
    }
    return rt;
}

LL gx(LL i, LL l, LL r, LL x)
{
    LL rt=++cnt;
    L[rt]=L[i], R[rt]=R[i], sum[rt]=sum[i]+1;//更新
    if(l<r)
    {
        if(x<=mid)
        {
            L[rt]=gx(L[i], l, mid, x);
        }
        else
        {
            R[rt]=gx(R[i], mid+1, r, x);
        }
    }
    return rt;
}

LL cx(LL u, LL v, LL l, LL r, LL k)
{
    if(l>=r)
    {
        return l;                        //找到区间
    }
    LL x=sum[L[v]]-sum[L[u]];
    if(x>=k)
    {
        return cx(L[u], L[v], l, mid, k);//递归查找
    }
    else
    {
        return cx(R[u], R[v], mid+1, r, k-x);//放4递归查找
    }
}

LL LSH()                               //离散化
{
    sort(b+1, b+1+n);
    m = unique(b+1, b+1+n)-b-1;
    for (LL i = 1; i <= n; i ++)
    {
        a[i] = lower_bound(b+1, b+1+m, a[i])-b;
    }
}

int main()
{
    while(~scanf("%lld%lld", &n, &q))
    {
        cnt = 0;
        for (LL i = 1; i <= n; i ++)
        {
            scanf("%lld", &a[i]);
            b[i] = a[i];
        }
        LSH();

        root[0] = JS(1, cnt);

        for(LL i=1;i<=n;i++)
        {
            root[i]=gx(root[i-1], 1, m, a[i]);//更新
        }

        while (q --)
        {
            LL x, y, z, f=0;
            scanf("%lld%lld", &x, &y);

            if(y-x+1<3)
            {
                printf("-1\n");
                continue;
            }

            LL a=b[cx(root[x-1], root[y], 1, m, (y-x+1))];
            LL c=b[cx(root[x-1], root[y], 1, m, (y-x))];

            for(LL Len=(y-x-1); Len>=1; Len--)
            {
                LL d=b[cx(root[x-1], root[y], 1, m, Len)];

                if((c+d)>a)
                {
                    printf("%lld\n", a+d+c);
                    f=1;
                    break;
                }
                else
                {
                    a=c;
                    c=d;
                }
            }
            if(!f)
            printf("-1\n");
        }
    }

    return 0;
}