• 2019hdu多校 Keen On Everything But Triangle


    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,Q≤1e5).

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

    Then follow Q lines. i-th of them contains two integers li,ri(1≤li≤ri≤N), 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×1e5.

    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
    

    Solution:

    可以发现,无法组成三角形的最劣条件便是斐波那契数列,而在本题数列最多到44项(ai<=1e9)

    于是我们便可以用主席树来维护区间第K大,然后暴力询问就OK了

    Code:

    #include<cstdio>
    #include<ctype.h>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define int long long
    using namespace std;
    const int N=1e5+1;
    int n,q,cnt,a[N],b[N],rt[N];
    struct SegTree{
    	int tot,ls[N*40],rs[N*40],sz[N*40];
    	void clear(){
    		tot=0;
    		memset(ls,0,sizeof(ls));
    		memset(rs,0,sizeof(rs));
    		memset(rt,0,sizeof(sz));
    	}
    	void build(int &q,int l,int r){
    		q=++tot;sz[q]=0;
    		if(l==r) return ;
    		int mid=l+r>>1;
    		build(ls[q],l,mid);
    		build(rs[q],mid+1,r);
    	}
    	void ins(int &q,int lst,int l,int r,int x){
    		q=++tot;
    		ls[q]=ls[lst],rs[q]=rs[lst];
    		sz[q]=sz[lst]+1;
    		if(l==r) return ;
    		int mid=l+r>>1;
    		if(mid>=x) ins(ls[q],ls[lst],l,mid,x);
    		else ins(rs[q],rs[lst],mid+1,r,x);
    	}
    	int query(int q,int p,int l,int r,int k){
    		if(l==r) return b[l];
    		int v=sz[ls[q]]-sz[ls[p]];
    		int mid=l+r>>1;
    		if(v>=k) return query(ls[q],ls[p],l,mid,k);
    		else return query(rs[q],rs[p],mid+1,r,k-v);
    	}
    }T;
    int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    	return x*f;
    }
    void solve(){T.clear();
    	for(int i=1;i<=n;i++)
    		a[i]=read(),b[i]=a[i];
    	sort(b+1,b+n+1);
    	cnt=unique(b+1,b+n+1)-b-1;
    	T.build(rt[0],1,cnt);
    	for(int i=1;i<=n;i++){
    		int v=lower_bound(b+1,b+cnt+1,a[i])-b;
    		T.ins(rt[i],rt[i-1],1,cnt,v);
    	}
    	for(int i=1;i<=q;i++){
    		int l=read(),r=read(),u=r-l+1,flag=0;
    		if(u<=2){puts("-1");continue;}
    		int a=T.query(rt[r],rt[l-1],1,cnt,u);
    		int b=T.query(rt[r],rt[l-1],1,cnt,--u);
    		while(u){
    			int v=T.query(rt[r],rt[l-1],1,cnt,--u);
    			if(v+b>a){
    				printf("%lld
    ",a+b+v);
    				flag=1;break;
    			}a=b,b=v;
    		}if(!flag) puts("-1");
    	}
    }
    signed main(){
    	while(~scanf("%lld%lld",&n,&q)) solve();
    	return 0;
    }
    
    
  • 相关阅读:
    bzoj 3944 Sum
    [BZOJ2693]jzptab
    luogu 3768 简单的数学题
    [ZJOI2015]幻想乡战略游戏
    [SDOI2017]数字表格
    [ZJOI2007]Hide 捉迷藏
    [SDOI2016]游戏
    [SPOJ10707]Count on a tree II
    [Luogu4177][CEOI2008]order
    [BZOJ4491]我也不知道题目名字是什么
  • 原文地址:https://www.cnblogs.com/NLDQY/p/11243254.html
Copyright © 2020-2023  润新知