题目链接:HDU - 6601
题意:多组输入,n个数字,q次询问,每次询问区间[L,R]内构成的最大三角形周长是多少,无法构成的话为-1。
如果三个数字无法构成三角形,那是不是某一条边大于等于另外两条边的和。
那考虑等于,在int范围内是不是最坏的情况是一个斐波那契数列,这个序列长度为44。
所以如果一个区间长度大于44的话,我一定可以在44次询问中找到答案,所以我们用主席树维护,每次询问区间第k小,k-1小,k-2小,直到k<=2,看这之间是否出现答案。
否则的话小于等于44,那也是直接跑过去就可以。
复杂度n*logn*44。
#include
using namespace std;
const int maxn=1e5+7;
typedef long long ll;
int b[maxn];
int a[maxn];
int m;
void quchong(int n){
sort(b+1,b+1+n);
m=unique(b+1,b+1+n)-b-1;
}
int getid(int x){
return lower_bound(b+1,b+1+m,x)-b;
}
int root[maxn];
struct Tree{
int lc,rc;
int sum;
}tree[4322089];
int tot;
int build(int l,int r){
int k=++tot;
tree[k].sum=0;
if(l==r){
return k;
}
int mid=(l+r)>>1;
tree[k].lc=build(l,mid);
tree[k].rc=build(mid+1,r);
return k;
}
int updata(int now,int l,int r,int id,int val){
int k=++tot;
tree[k]=tree[now];
if(l==r){
++tree[k].sum;
return k;
}
int mid=(l+r)>>1;
if(id<=mid) tree[k].lc=updata(tree[now].lc,l,mid,id,val);
else tree[k].rc=updata(tree[now].rc,mid+1,r,id,val);
tree[k].sum=tree[tree[k].lc].sum+tree[tree[k].rc].sum;
return k;
}
int myfind(int L,int R,int l,int r,int h){
if(l==r) return l;
int val=tree[tree[R].lc].sum-tree[tree[L].lc].sum;
int mid=(l+r)>>1;
if(h<=val) return myfind(tree[L].lc,tree[R].lc,l,mid,h);
return myfind(tree[L].rc,tree[R].rc,mid+1,r,h-val);
}
bool check(int id1,int id2,int id3){
int x=b[id1],y=b[id2],z=b[id3];
if(x+1LL*y>z&&x-y2){//放心跑就可以。
int id1=myfind(root[l-1],root[r],1,m,k);
int id2=myfind(root[l-1],root[r],1,m,k-1);
int id3=myfind(root[l-1],root[r],1,m,k-2);
--k;
if(check(id1,id2,id3)){
res=b[id1]+1LL*b[id2]+1LL*b[id3];
break;
}
}
printf("%lld\n",res);
}
}
return 0;
}