HDOJ_Multi_school Day 2 T11 Keen On Everything But Triangle


title: HDOJ_Multi_school Day 2 T11
date: 2019-07-28 12:40:00
tags: [HDOJ_Multi_chool,solved,done]
mathjax: true
toc: true

这题主要是对主席树的考察

需要的知识:
线段树(Segment Tree)
权值线段树,主席树,
斐波那契数列(Fibonacci sequence)

Keen On Everything But Triangle

Problem Description

N N N sticks are arranged in a row, and their lengths are a 1 , a 2 , . . . , a N a_1,a_2,...,a_N a1,a2,...,aN.

There are Q Q Q querys. For i − t h i-th ith of them, you can only use sticks between l i − t h l_i-th lith to r i − t h r_i-th rith. Please output the maximum circumference of all the triangles that you can make with these sticks, or print − 1 −1 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 ≤ 1 0 5 ) N,Q( N,Q \leq 10^5) N,Q(N,Q105).

The second line contains N N N integers, the i − t h i-th ith integer a i ( 1 ≤ a i ≤ 1 0 9 ) a_i(1 \leq a_i \leq 10^9) ai(1ai109) of them showing the length of the i − t h i-th ith stick.

Then follow $Q $lines. i − t h i-th ith of them contains two integers l i , r i ( 1 ≤ l i ≤ r i ≤ N ) l_i,r_i(1 \leq l_i \leq r_i \leq N) li,ri(1liriN), meaning that you can only use sticks between l i − t h l_i-th lith to r i − t h r_i-th rith.

It is guaranteed that the sum of N s N_s Ns and the sum of Q s Q_s Qs in all test cases are both no larger than 4 × 1 0 5 4×10^5 4×105.

Output

For each test case, output Q Q 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

想法

这题非常巧妙地将主席树和斐波那契数列结合在了一起

首先要求三条边构成三角形就意味着 a + b > c a+b>c a+b>c , 想到 a + b = c a+b=c a+b=c 就是斐波那契兔子数列,再看范围得知最多到数列的第45项

这样为题就装换为求区间最大值、次大值、次次大值、次次次大值…

求区间第K大值,这个在就是主席树的模板题了。

The Code Of My Program

/*
*@Author:   ChenShou
*@Language: C++
*/
//#include <bits/stdc++.h>
#include<iostream>// 
#include<algorithm>//
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>//
#include<bitset>
#include<queue>
#include<deque>
#include<stack>
#include<cmath>
#include<list>
#include<map>
#include<set>

//#define DEBUG
#define RI register int
#define endl "\n"

using namespace std;
typedef long long ll;
//typedef __int128 lll;
const int N=100000+10;
const int M=100000+10;
const int MOD=1e9+7;
const double PI = acos(-1.0);
const double EXP = 1E-9;
const int INF = 0x3f3f3f3f;
const int maxn=1e5+3;

ll  cnt,root[maxn],a[maxn];
vector<int>v;
struct node{ll l,r,sum;}T[maxn*40];
ll getid(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}

void update(ll l,ll r,ll &x,ll y,ll pos){
	T[++cnt]=T[y],T[cnt].sum++,x=cnt;
	if(l==r)return;
	ll mid=(l+r)>>1;
	if(mid>=pos)update(l,mid,T[x].l,T[y].l,pos);
	else update(mid+1,r,T[x].r,T[y].r,pos);
}

ll query(ll l,ll r,ll x,ll y,ll k){
	if(l==r)return l ;
	ll mid=(l+r)>>1;
	ll sum=T[T[y].l].sum-T[T[x].l].sum;
	if(sum>=k)return query(l,mid,T[x].l,T[y].l,k);
	else return query(mid+1,r,T[x].r,T[y].r,k-sum);
}
int main(){
#ifdef DEBUG
    freopen("input.in", "r", stdin);
    //freopen("output.out", "w", stdout);
#endif
    //ios::sync_with_stdio(false);
    //cin.tie(0);
    //cout.tie(0);
    //scanf("%d",&t);
    //while(t--){
    //}
	ll n,m;
    while(scanf ( "%lld %lld" , &n , &m )!=EOF){
    	
    ll t,x,y,k;
    v.clear();cnt = 0;
    for( ll i = 1 ; i <= n ; i++ ){scanf ( "%lld" , & a[i] ),v.push_back(a[i]);}
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    for( ll i = 1 ; i <= n ; i++ ){
    	update ( 1 , n , root[i] , root[i-1] , getid(a[i])) ; 
    }
    for( ll i = 1 ; i <= m ; i++ ){
    	int flag=0;
    	ll a,b,c;
    	scanf ( "%lld %lld" , &x , &y ) ; 
    	for(ll i=y-x+1;i>=3;i--){
			 a=v[ query ( 1 , n , root[x-1] , root[y] , i ) - 1 ];
    		 b=v[ query ( 1 , n , root[x-1] , root[y] , i-1 ) - 1 ];
   			 c=v[ query ( 1 , n , root[x-1] , root[y] , i-2 ) - 1 ];
    		if(b+c>a){
    			flag=1;
    			break;
    		}
    	}   
		if(flag)printf("%lld\n",a+b+c);
		else printf("-1\n");
    }
    
	}
#ifdef DEBUG
    printf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC);
#endif
    //cout << "Hello world!" << endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值