ACM的探索之Keen On Evrything But Triangle(我觉得可以很接近啦!!)
#include<bits/stdc++.h> using namespace std; int main() { int n,q,l,r; while(cin>>n>>q) { vector<int> a(n); for(int i=0;i<n;i++) cin>>a[i]; while(q--) { cin>>l>>r; vector<int> b(r-l+1); for(int i=0;i<r-l+1;i++) b[i]=a[i+l-1]; sort(b.begin(),b.end()); int len=r-l+1; int x=b[len-1]; int y=b[len-2]; int z=b[len-3]; cout<<x+y+z<<endl; } } return 0; } //好接近了,但是因为超时被卡住了!
接下来是题目喽:
援引自https://blog.csdn.net/xizi_ghq https://blog.csdn.net/xizi_ghq/article/details/97136436
题意:给出一个数列,询问任意区间,区间内所组成的最大的三角形周长是多少?
首先要明白斐波那契的一个性质,刚刚好不能够组成三角形,然后根据这个性质,1e9的范围内,如果一直不能构成三角形,最大只有47个数(47层)。这样我们从每个区间取出最大的47个数,然后来判断这47个数满足题意的三角形周长就可以了。
很明显主席树查询第k大模板。
大佬的代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int M=1e5+50; 4 int n,q,d[M],b[M],root[M],cnt; 5 struct Node{int l,r,sum;}t[40*M]; 6 void build(int &rot,int l,int r){ 7 rot=++cnt; 8 t[rot].sum=0; 9 if(l==r)return ; 10 int mid=(l+r)>>1; 11 build(t[rot].l,l,mid); 12 build(t[rot].r,mid+1,r); 13 } 14 void update(int &rot,int l,int r,int last ,int v){ 15 rot=++cnt; 16 t[rot].l=t[last].l; 17 t[rot].r=t[last].r; 18 t[rot].sum=t[last].sum+1; 19 if(l==r)return ; 20 int mid=(l+r)>>1; 21 if(v<=mid)update(t[rot].l,l,mid,t[last].l,v); 22 if(mid<v)update(t[rot].r,mid+1,r,t[last].r,v); 23 } 24 bool judge(int x,int y,int z){ 25 char xx[3]; 26 xx[0]=x; 27 xx[1]=y; 28 xx[2]=z; 29 sort(xx,xx+3); 30 if(xx[0]+xx[1]<=xx[2])return false; 31 return true; 32 } 33 int ask(int pre,int now,int l,int r,int k){ 34 if(l==r)return l; 35 int mid=(l+r)>>1,num=t[t[now].r].sum-t[t[pre].r].sum; 36 if(k<=num)return ask(t[pre].r,t[now].r,mid+1,r,k); 37 return ask(t[pre].l,t[now].l,l,mid,k-num); 38 } 39 int main(){ 40 while(scanf("%d%d",&n,&q)!=EOF){ 41 cnt=0; 42 43 for(int i=1;i<=n;i++){ 44 scanf("%d",d+i); 45 b[i]=d[i]; 46 } 47 sort(b+1,b+n+1); 48 int sz=unique(b+1,b+n+1)-(b+1); 49 for(int i=1;i<=n;i++)d[i]=lower_bound(b+1,b+sz+1,d[i])-b; 50 build(root[0],1,sz); 51 for(int i=1;i<=n;i++)update(root[i],1,sz,root[i-1],d[i]); //通过上个树,来更新这个树 52 long long res[55]; 53 for(int x,y,k,mx,f,i=1;i<=q;i++){ 54 scanf("%d%d",&x,&y); 55 mx=min(50,y-x+1); 56 if(mx<3){ 57 printf("-1\n"); 58 continue; 59 } 60 for(int j=1;j<=mx;j++) res[j] = b[ask(root[x-1],root[y],1,sz,j)]; //找到第k大的数字 61 f=0; 62 for(int j=3;j<=mx;j++){ 63 if(res[j]+res[j-1]>res[j-2]){ 64 f=1; 65 printf("%lld\n",res[j]+res[j-1]+res[j-2]); 66 break; 67 } 68 } 69 if(!f)printf("-1\n"); 70 } 71 } 72 return 0; 73 }
tql !!!!!!