题意:求区间[ l , r ]能构成三角形周长最大的,不存在就输出-1
解:主席树模版
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 300000;
int sum[maxn*20+5];//sum为森林的不同根结点
struct E {
ll num;
int l,r;
} t[maxn*20+5]; //t为tree树
int n,sz,m,cnt;
ll a[maxn],b[maxn];
int build(int l,int r) {
int now = ++cnt;
int mid = (l+r)>>1;
if(l<r) {
t[now].l = build(l,mid);
t[now].r = build(mid+1,r);
}
return now;
}
int update(int l,int r,int last,int p) {
int now = ++cnt;
t[now].num = t[last].num+1;
t[now].l = t[last].l;
t[now].r = t[last].r;
int mid = (l + r)>>1;
if(l<r) {
if(p<=mid)t[now].l = update(l,mid,t[last].l,p);
else t[now].r = update(mid+1,r,t[last].r,p);
}
return now;
}
ll query(int u,int v,int l,int r,int k) {
if(l==r)return l;
// v 左孩子包含点个数减去 u 左孩子包含点的个数
int tmp = t[t[v].l].num - t[t[u].l].num;
int mid = (l+r)>>1;
if(k<=tmp)return query(t[u].l,t[v].l,l,mid,k);
else return query(t[u].r,t[v].r,mid+1,r,k - tmp);
}
bool judge(ll x,ll y,ll z){
if(y+z>x){
return true;
}
return false;
}
int main() {
ll t1,t2,t3;
while(scanf("%d %d",&n,&m)==2) {
for(int i=1; i<=n; i++)scanf("%lld",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
sz = unique(b+1,b+n+1) - (b+1);
cnt = 0;
sum[0] = build(1,sz);//建立空树
for(int i=1; i<=n; i++) a[i] = lower_bound(b+1,b+sz+1,a[i]) - b;
for(int i=1; i<=n; i++) sum[i] = update(1,sz,sum[i-1],a[i]);
while(m--) {
int u,v,k = 4,flag=0;
scanf("%d %d",&u,&v);
if(v-u+1<3){
printf("-1\n");
continue;
}
int len = v - u + 1;
t1 = query(sum[u-1],sum[v],1,sz,len-1+1); t1 = b[t1];
t2 = query(sum[u-1],sum[v],1,sz,len - 2+1); t2 = b[t2];
t3 = query(sum[u-1],sum[v],1,sz,len-3+1); t3 = b[t3];
while(1){
if(judge(t1,t2,t3)){
flag = 1;
break;
}
if(k>len)break;
t1 = t2; t2 = t3;
t3 = query(sum[u-1],sum[v],1,sz,len-k+1); t3 = b[t3];
k++;
}
if(flag)printf("%lld\n",t1+t2+t3);
else printf("-1\n");
}
}
return 0;
}