题目链接
题目大意
给你一个数组,有m次询问,每次询问有一个【l,r】在这个区间里找到可以组成三角形的三个数字,使得三角形的周长最大。
解题思路
这个题的思路有点巧妙。
我们想找到周长最大的三角形,就在这个区间里询问第一大,第二大,第三大不行的话找第二大,第三大,第四大等等,寻找的时候可以用静态主席树来维护。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,m;
struct node
{
int l,r,sum;
};
node e[N*40];
int root[N*2],cnt;
long long a[N],b[N];
void init()
{
cnt=1;
e[0].l=e[0].r=e[0].sum;
memset(root,0,sizeof(root));
}
void update(int num,int &rt,int l,int r)
{
e[cnt++]=e[rt];
rt=cnt-1;
e[rt].sum++;
if(l==r)
return ;
int mid=(l+r)/2;
if(num<=mid)
update(num,e[rt].l,l,mid);
else
update(num,e[rt].r,mid+1,r);
}
int que(int i,int j,int k,int l,int r)
{
int d=e[e[j].l].sum-e[e[i].l].sum;
if(l==r)
return l;
int mid=(l+r)/2;
if(k<=d)
return que(e[i].l,e[j].l,k,l,mid);
else
return que(e[i].r,e[j].r,k-d,mid+1,r);
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
init();
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
b[i]=a[i];
}
sort(b+1,b+1+n);
int mm=unique(b+1,b+1+n)-b-1;
for(int i=1;i<=n;i++)
{
root[i]=root[i-1];
int aa=lower_bound(b+1,b+1+mm,a[i])-b;
update(aa,root[i],1,mm);
}
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
int len=y-x+1;
if(len<3)
{
printf("-1\n");
continue;
}
long long ans=-1;
for(int i=len;i>=3;i--)
{
long long x1=b[que(root[x-1],root[y],i,1,mm)];
long long x2=b[que(root[x-1],root[y],i-1,1,mm)];
long long x3=b[que(root[x-1],root[y],i-2,1,mm)];
//printf("%d %d %d\n",x1,x2,x3);
if(x2+x3>x1&&x1+x2>x3&&x1+x3>x2)
{
ans=x1+x2+x3;
break;
}
}
printf("%lld\n",ans);
}
}
return 0;
}