zoukankan      html  css  js  c++  java
  • 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
    ",ans);
                else printf("-1
    ");
            }
        }
            
        return 0;
    }
  • 相关阅读:
    【CSS】419- 彻底搞懂word-break、word-wrap、white-space
    【Webpack】418- 深度优化 Webpack 性能,翻倍构建性能
    【React】417- React中componentWillReceiveProps的替代升级方案
    巩固java(二)----JVM堆内存结构及垃圾回收机制
    巩固java(一)----java与对象
    Latex 公式换行问题,(换行,等号对齐)
    Android FoldingLayout 折叠布局 原理及实现(二)
    19.最省钱的app发短信方法
    Android FoldingLayout 折叠布局 原理及实现(一)
    18.app后端如何实现LBS
  • 原文地址:https://www.cnblogs.com/chen99/p/11294104.html
Copyright © 2011-2022 走看看