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
NNN sticks are arranged in a row, and their lengths are a1,a2,...,aNa_1,a_2,...,a_Na1,a2,...,aN.
There are QQQ querys. For i−thi-thi−th of them, you can only use sticks between li−thl_i-thli−th to ri−thr_i-thri−th. 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≤105)N,Q( N,Q \leq 10^5)N,Q(N,Q≤105).
The second line contains NNN integers, the i−thi-thi−th integer ai(1≤ai≤109)a_i(1 \leq a_i \leq 10^9)ai(1≤ai≤109) of them showing the length of the i−thi-thi−th stick.
Then follow $Q $lines. i−thi-thi−th of them contains two integers li,ri(1≤li≤ri≤N)l_i,r_i(1 \leq l_i \leq r_i \leq N)li,ri(1≤li≤ri≤N), meaning that you can only use sticks between li−thl_i-thli−th to ri−thr_i-thri−th.
It is guaranteed that the sum of NsN_sNs and the sum of QsQ_sQs in all test cases are both no larger than 4×1054×10^54×105.
Output
For each test case, output QQQ 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>ca+b>ca+b>c , 想到 a+b=ca+b=ca+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;
}