4235. 【五校联考5day1】序列

63 篇文章 0 订阅

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

6
7 1 3 4 5 1
3
2
1 3 5
2

Sample Output

3 5 7
4 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

Solution

我们发现其实做序列前50个数就可以了。因为如果我们要使一个序列中任意3个数不能组成三角形的长度要尽量长的话,那么最坏的情况就是,第一个数是0,第二个数是1,第三个数是1,第四个数是2,第五个数是3,以此类推......因为若一个数小于前面两个数之和,那么这个数和前面两个数一定能构成一个三角形,因为a的范围是小于10^9次方的,所以当这个序列的长度大于50时,这个数就大于了10^9所以我们只要找前50个数就一定能找出3个数使得它们能够成三角形。

 

Code

#include<cstdio> 
#include<cstring>
#include<algorithm>
#define N 100010
using namespace std;
int n,m,k,x,y,a1,a2,a3,a[N],ans[4],bz;
int pd(int x,int y,int z){
	int m1=min(x,min(y,z)),m2;
	if(m1==x) m2=y<z?y:z;
	else if(m1==y) m2=x<z?x:z;
	else if(m1==z) m2=x<y?x:y;
	if(m1+m2>x+y+z-m1-m2) return 1;
	return 0;
}
int main(){
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	scanf("%d",&m);
	while(m--){
		scanf("%d",&k);
		if(k==1){
			scanf("%d%d",&x,&y);
			a[x]=y;
		}
		else{
			ans[1]=-1;ans[2]=-1;ans[3]=-1;
			for(int i=3;i<=47;i++){
				for(int j=1;j<=i-1;j++){
					for(int k=1;k<=j-1;k++){
						if(pd(a[i],a[j],a[k])){
							ans[1]=a[i];ans[2]=a[j];ans[3]=a[k];
							a1=i;a2=j;a3=k;
							break;
						}
					}
					if(ans[1]!=-1) break;
				}
				if(ans[1]!=-1) break;
			}
			sort(ans+1,ans+4);
			printf("%d %d %d\n",ans[1],ans[2],ans[3]);
		}
	}
	return 0;
}


作者:zsjzliziyang 
QQ:1634151125 
转载及修改请注明 
本文地址:https://blog.csdn.net/zsjzliziyang/article/details/86683520

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值