hdu6601 Keen On Everything But Triangle 主席树+斐波那契数列妙用

发布时间 2023-03-28 01:19:45作者: liyishui

题意:

给定序列a,ai为第i根木棍长度,给出q个询问

每次问[L,R]内能构成三角形的最大周长是多少

题解:

属于那种没有往这个方向想就很难想到,然后一直想不到的题2333

因为周长要最大,贪心地优先考虑第一大,第二大,第三大能不能组成合法的三角形

假设不行,那第一根肯定是废了

因为任意两边之和大于第三边->最小的两边之和要大于第三边

第二和第三都搞不定第一,那其他的更不行

接下来继续考虑第二大,第三大,第四大...

但是会担心复杂度怎么办?

怎么办?考虑最坏情况,一直找不到,且构成斐波那契关系

则斐波那契的第45项数已经超过1e9了

说明如果有答案,则在45次内必能找到

如果-1,也能在45次内确定(因此区间长度>=45的话肯定是会有答案的,如果一定没有,则在45次内也能知道,不会tle)

 

#include<bits/stdc++.h>
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long ll;
using namespace std;
const int N=2e5+5;
const int maxn=N*40;
int cnt,n,m,q;
int b[N],a[N],tmp[N];
struct pesis_seg{
    int ls[maxn],rs[maxn],rt[maxn],sum[maxn];
    void build(int &o,int l,int r){
        o=++cnt;
        if(l==r) {
            return;
        }
        int mid=(l+r)>>1;
        build(ls[o],l,mid);
        build(rs[o],mid+1,r);
    }
    int update(int o,int l,int r,int pos){
        int oo=++cnt;//相当于动态开点 
        ls[oo]=ls[o];rs[oo]=rs[o];sum[oo]=sum[o]+1;
        if(l==r){
            return oo;
        }
        int mid=(l+r)>>1;
        if(pos<=mid) ls[oo]=update(ls[o],l,mid,pos);
        else rs[oo]=update(rs[o],mid+1,r,pos);
        return oo;
    }
    int query(int kth,int u,int v,int l,int r){
        if(l==r){
            return l;
        }
        int mid=(l+r)>>1;
        int x=sum[ls[v]]-sum[ls[u]];
        //cout<<kth<<" "<<u<<" "<<v<<" "<<l<<" "<<r<<" "<<x<<endl;
        if(x>=kth) return query(kth,ls[u],ls[v],l,mid);
        else return query(kth-x,rs[u],rs[v],mid+1,r);
    }
}t;
int main(){
    //fastio;
    //freopen("lys.in","r",stdin);
    //freopen("lys.in","r",stdin);
    while(scanf("%d %d",&n,&q)!=EOF){
    
    for(int i=1;i<=cnt;i++) t.rt[i]=t.sum[i]=t.ls[i]=t.rs[i]=0;
    cnt=0;
    
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
    sort(b+1,b+n+1);
    int len=unique(b+1,b+n+1)-(b+1);
    t.build(t.rt[0],1,len);
    for(int i=1;i<=n;i++){
        //    int update(int o,int pre,int l,int r,int pos,int val){
        int pos=lower_bound(b+1,b+len+1,a[i])-b;
        t.rt[i]=t.update(t.rt[i-1],1,len,pos);
    }
    
    for(int ii=1;ii<=q;ii++){
        int l,r;
        scanf("%d%d",&l,&r);
        int mx=r-l+1;
        bool flag=false;
        int v[5];
        for(int i=1;i<=mx-2;i++){
            v[1]=b[t.query(mx-i+1,t.rt[l-1],t.rt[r],1,len)];
            v[2]=b[t.query(mx-i,t.rt[l-1],t.rt[r],1,len)];
            v[3]=b[t.query(mx-i-1,t.rt[l-1],t.rt[r],1,len)];
            if(v[1]<v[2]+v[3]){
                flag=true;
                ll ans=(ll)v[1]+v[2]+v[3];
                printf("%lld\n",ans);
                break;
            }
        }
        if(!flag) printf("%d\n",-1);
    }
    
    }
}