HDU 6601 Keen On Everything But Triangle(静态主席树)

找区间内三条边可组成周长最长的三角形,因为三角形边长关系,最坏情况就是斐波那契数,从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] ];//找第k大  第k小修改这里 然后下面左右子树先找的顺序也要改
    if(res>=k)query(mid+1,r,R[tl],R[tr],k);
    else query(l,mid,L[tl],L[tr],k-res);
}

int main()
{
//    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值