这是我的题,做的时候有各种问题哈哈哈,我还是换个模版吧,主席树的模版也太坑了,太难过了
https://vjudge.net/contest/315187#problem/K
题意:其实题意就是给你一个数组,然后m个查询,让你查找区间里的最大能构成三角形的,三个边长之和。
题解:这个题其实很好做,就是每次查找区间里最大,次大,次次大的三条边判断能否构成三角形,如果不行,再判断2,3,4……
//这里是区间第几小的模版
#include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn=1e5+5;;
int n,q,m,cnt=0;
int a[maxn],b[maxn],T[maxn];
int sum[maxn<<6],L[maxn<<6],R[maxn<<6];
int build(int l,int r)
{
int rt=++cnt;
sum[rt]=0;
int mid=(l+r)/2;
if(l<r)
{
L[rt]=build(l,mid);
R[rt]=build(mid+1,r);
}
return rt;
}
int update(int pre,int x,int l,int r)
{
int rt=++cnt;
L[rt]=L[pre];
R[rt]=R[pre];
sum[rt]=sum[pre]+1;
int mid=(l+r)/2;
if(l<r)
{
if(x<=mid)L[rt]=update(L[rt],x,l,mid);
else R[rt]=update(R[rt],x,mid+1,r);
}
return rt;
}
int query(int u,int v,int l,int r,int k)
{
if(l==r)
return l;
int x=sum[L[v]]-sum[L[u]];
int mid=(l+r)/2;
if(x>=k)
return query(L[u],L[v],l,mid,k);
else
return query(R[u],R[v],mid+1,r,k-x);
}
int main()
{
while(~scanf("%d %d",&n,&q))
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
b[i] = a[i];
}
sort(b+1,b+n+1);
m=unique(b+1,b+1+n)-b-1;
T[0]=build(1,m);
for(int i = 1;i <= n;i++)
{
int k=lower_bound(b,b+m,a[i])-b;
T[i]=update(T[i-1],k,1,m);
}
while(q--)
{
int x,y;
scanf("%d %d",&x,&y);
int k=y-x+1;
ll ans;
int flag=0;
int x1,x2,x3;
for(int i=k;i>=3;i--)
{
if(i==k)
{
x1=query(T[x-1],T[y],1,m,i);
x2=query(T[x-1],T[y],1,m,i-1);
x3=query(T[x-1],T[y],1,m,i-2);
}
else
{
x1=x2;
x2=x3;
x3=query(T[x-1],T[y],1,m,i-2);
}
if(1ll*b[x2]+b[x3]>1ll*b[x1])
{
ans=1ll*b[x1]+b[x2]+b[x3];
flag=1;
break;
}
}
if(flag==1)
printf("%lld\n",ans);
else
printf("-1\n");
}
}
return 0;
}