hdu6601 主席树

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

Problem Description
N sticks are arranged in a row, and their lengths are a1,a2,...,aN.

There are Q querys. For i-th of them, you can only use sticks between li-th to ri-th. Please output the maximum circumference of all the triangles that you can make with these sticks, or print 1 denoting no triangles you can make.
 

 

Input
There are multiple test cases.

Each case starts with a line containing two positive integers N,Q(N,Q105).

The second line contains N integers, the i-th integer ai(1ai109) of them showing the length of the i-th stick.

Then follow Q lines. i-th of them contains two integers li,ri(1liriN), meaning that you can only use sticks between li-th to ri-th.

It is guaranteed that the sum of Ns and the sum of Qs in all test cases are both no larger than 4×105.
 

 

Output
For each test case, output Q lines, each containing an integer denoting the maximum circumference.
 

 

Sample Input
5 3
2 5 6 5 2
1 3
2 4
2 5
 

 

Sample Output
13
16
16
 
主席树求最大三条边,如果三边能组成三角形即为答案,否则再找第二大第三大第四大的边,一直找到符合的
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100005
#define ll long long
int T[maxn*20],L[maxn*20],R[maxn*20],sum[maxn*20],tot;
ll a[maxn],b[maxn];
inline int update(int pre,int l,int r,int x)
{
    int rt=++tot;
    L[rt]=L[pre];
    R[rt]=R[pre];
    sum[rt]=sum[pre]+1;
    if(l<r)
    {
        int mid=l+r>>1;
        if(x<=mid)L[rt]=update(L[pre],l,mid,x);
        else R[rt]=update(R[pre],mid+1,r,x);
    }
    return rt;
}
inline int query(int u,int v,int l,int r,int k)
{
    if(l>=r)return l;
    int x=sum[L[v]]-sum[L[u]],mid=l+r>>1;
    if(x>=k)return query(L[u],L[v],l,mid,k);
    else return query(R[u],R[v],mid+1,r,k-x);
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        int len=unique(b+1,b+1+n)-b-1;
        T[0]=L[0]=R[0]=sum[0]=tot=0;
        for(int i=1;i<=n;i++)
        {
            int pos=lower_bound(b+1,b+1+len,a[i])-b;
            T[i]=update(T[i-1],1,len,pos);
        }
        for(int i=1;i<=m;i++)
        {
            int l,r;
            int flag=0;
            ll ans=0;
            scanf("%d%d",&l,&r);
            for(int i=r-l+1;i>=3;i--)
            {
                ll A=b[query(T[l - 1],T[r],1,len,i)];
                ll B=b[query(T[l - 1],T[r],1,len,i-1)];
                ll C=b[query(T[l - 1],T[r],1,len,i-2)];
                if(B+C>A)
                {
                    flag=1;
                    ans=A+B+C;
                    break;
                }
            }
            if(flag)printf("%lld\n",ans);
            else printf("-1\n");
        }
    }
        
    return 0;
}

 

posted on 2019-08-03 10:59  che027  阅读(151)  评论(0编辑  收藏  举报

导航