题解
序列 (Standard IO)
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
Description
Fiugou想要在一个长度为N的序列A中找到不同位置的三个数,以这三个数为三边长来构成一个三角形。但是它希望在满足条件下,这三个数的位置尽量靠前。具体地,设这三个数的为Ai,Aj,Ak(i<j<k), Fiugou希望k尽量小;当k相等时,满足j尽量小;当k,j均相等时,满足i尽量小。
但是这个序列中的数可能会发生变化。所以Fiugou给出了M个操作,形式如下:
1 x y:将Ax改为y
2:查询最优的合法解,从小到大给出这三个数(而不是位置)。
Input
第一行一个整数N,代表序列的长度。
第二行有N个整数,代表初始序列。
第三行一个整数M,代表操作的个数。
接下来M行操作,两种操作格式如上所述。
Output
共M行,每行三个数,从小到大给出。如果不存在,输出-1 -1 -1。
Sample Input
67 1 3 4 5 1321 3 52
Sample Output
3 5 74 5 7
Data Constraint
对于10%的数据, N<=10, M<=5
对于30%的数据, N<=100, M<=25
对于50%的数据, N<=1000, M<=1000
对于100%的数据, N<=100000, M<=1000
对于100%的数据, 0<=Ai<=10^9, 1<=x<=N, 0<=y<=10^9
数据很水导致题目直接很水,暴力枚举就可以过了。那个N的取值范围是拿来骗你的。因为三角形的任意两边之和大于第三边,任意三个数满足a>=b+c,就无解,amax是10^9,b和c从1开始枚举,满足第n项大于等于前两数之和,得到一个数列1,1,2,3,5,8,13,21,34,55,89......任意三个数满足a>=b+c的序列中最大的一个数不超过10^9的位置是50,所以在50之内一定可以枚举出一对解,且该解就是最优解,如果50之内都没有解,那么一定有a>10^9或者就是无解,所以n只用枚举到50。那么直接枚举三条边,最多O(m*50^3)的复杂度,就可以过了。
因为j>k>p(分别对应题目中的k,j,i),所以先枚举j,再枚举k,最后枚举p,保证第一个找出来的满足条件的是最优解。
附上代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 int n,m,x,g,o; 7 long long y; 8 long long a[100005]; 9 int main() 10 { 11 scanf("%d",&n); 12 for(int i=1;i<=n;i++) 13 scanf("%lld",&a[i]); 14 scanf("%d",&m); 15 for(int i=1;i<=m;i++) 16 { 17 scanf("%d",&o); 18 if(o==1) 19 { 20 scanf("%d%lld",&x,&y); 21 a[x]=y; 22 } 23 else if(o==2) 24 { 25 g=0; 26 for(int j=3;j<=n;j++) 27 { 28 for(int k=2;k<=j-1;k++) 29 { 30 for(int p=1;p<=k-1;p++) 31 { 32 if(a[j]+a[k]>a[p]&&a[j]+a[p]>a[k]&&a[k]+a[p]>a[j]) 33 { 34 long long h[4]; 35 h[1]=a[j];h[2]=a[k];h[3]=a[p]; 36 sort(h+1,h+4); 37 for(int j=1;j<=3;j++) 38 printf("%lld ",h[j]); 39 printf("\n"); 40 g=1; 41 break; 42 } 43 } 44 if(g==1) break; 45 } 46 if(g==1) break; 47 } 48 if(g==0) 49 printf("-1 -1 -1\n"); 50 } 51 } 52 return 0; 53 }
其它两组测试数据:https://files.cnblogs.com/files/grt-lty-love-forever/A%28StandardIO%29.rar
by:ルオ?テンイの锦依卫
未经作者允许,禁止转载!
原文地址:https://www.cnblogs.com/grt-lty-love-forever/p/10332067.html