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 i−th of them, you can only use sticks between l i − t h l_i-th li−th to r i − t h r_i-th ri−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 ≤ 1 0 5 ) N,Q( N,Q \leq 10^5) N,Q(N,Q≤105).
The second line contains N N N integers, the i − t h i-th i−th integer a i ( 1 ≤ a i ≤ 1 0 9 ) a_i(1 \leq a_i \leq 10^9) ai(1≤ai≤109) of them showing the length of the i − t h i-th i−th stick.
Then follow $Q $lines. i − t h i-th i−th 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(1≤li≤ri≤N), meaning that you can only use sticks between l i − t h l_i-th li−th to r i − t h r_i-th ri−th.
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;
}