1011 Keen On Everything But Triangle
Keen On Everything But Triangle
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2617 Accepted Submission(s): 578
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≤105).
The second line contains N integers, the i-th integer ai(1≤ai≤109) 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×105.
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
Source
2019 Multi-University Training Contest 2
题意:有N根木棒,每根长度为ai,有q次询问,每次询问一个区间内能组成的三角形的最大周长
题解:易知结果就是求能组成三角形的第i大和第i+1大和第i+2大之和。主席树求区间第k大每次修改和查询的时间复杂度为logn,针对本题,每次询问给一个区间,需要进行O(n)次查询第k大来判断是否可以构成三角形,那么每次询问复杂度就是O(nlogn),q次就是O(nqlogn),显然超时。但是实际上最坏的情况下:木棒长度构成了斐波那契数列,但是斐波那契数列元素在第40+项的时候就已经超过1e9了,所以复杂度最多为O(50*qlogn)可以通过
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define debug(x) cout<<#x<<" is "<<x<<endl;
const int maxn=1e5+5;
struct node{
int l;
int r;
int sum;
}no[maxn*45];
int cnt,root[maxn];
ll a[maxn],b[maxn],ac[55];
void build(int &rt,int l,int r){
rt=++cnt;
no[cnt].sum=0;
if(l==r)return;
int mid=(l+r)>>1;
build(no[cnt].l,l,mid);
build(no[cnt].r,mid+1,r);
}
void update(int &rt,int l,int r,int last,int v){
rt=++cnt;
no[cnt].sum=no[last].sum+1;
no[cnt].l=no[last].l;
no[cnt].r=no[last].r;
if(l==r)return;
int mid=(l+r)>>1;
if(mid>=v)update(no[cnt].l,l,mid,no[last].l,v);
else update(no[cnt].r,mid+1,r,no[last].r,v);
}
int query(int L,int R,int l,int r,int k){
if(l==r)return l;
int num=no[no[R].r].sum-no[no[L].r].sum;
int mid=(l+r)>>1;
if(num>=k)return query(no[L].r,no[R].r,mid+1,r,k);
else return query(no[L].l,no[R].l,l,mid,k-num);
}
int main(){
int n,q;
while(scanf("%d%d",&n,&q)==2){
cnt=0;
for(int i=1;i<=n;i++){scanf("%lld",&a[i]);b[i]=a[i];}
sort(b+1,b+1+n);
int siz=unique(b+1,b+1+n)-(b+1);
for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+1+siz,a[i])-b;
build(root[0],1,siz);
for(int i=1;i<=n;i++)update(root[i],1,siz,root[i-1],a[i]);
while(q--){
int c,d;
scanf("%d%d",&c,&d);
if(d<c)swap(c,d);
if(d-c+1<3){printf("-1\n");continue;}
int maxx=min(50,d-c+1);
for(int i=1;i<=maxx;i++){
ac[i]=b[query(root[c-1],root[d],1,siz,i)];
}
ll ak=-1;
for(int i=1;i+2<=maxx;i++){
if(ac[i]<ac[i+1]+ac[i+2]){
ak=ac[i]+ac[i+1]+ac[i+2];
break;
}
}
printf("%lld\n",ak);
}
}
return 0;
}