JZOJ4235序列【O(n^3)暴力】

本文探讨了在一个序列中寻找能构成三角形的三个数的问题,重点在于优化查询过程并实时更新序列。通过暴力枚举策略,实现了在序列变化时快速定位符合条件的三角形边长,确保解的最优性和效率。

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&Output

第一行一个整数N,代表序列的长度。
第二行有N个整数,代表初始序列。
第三行一个整数M,代表操作的个数。
接下来M行操作,两种操作格式如上所述。

共M行,每行三个数,从小到大给出。如果不存在,输出-1 -1 -1。

Example

input

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

output

3 5 7
4 5 7

Solution

0%~99%:细节问题
100%:暴力枚举这三个数,已找到就退(因为这样使得i,j,k最小)
(3<=k<=n,2<=j<k,1<=i,<j)然后更新ans[1~3],之后直接break
这样可以在O(m×n3)O(m\times n^3)O(m×n3)的时间内卡过去
This is speed.
参考code在这里插入图片描述
其实不长的啦,打了读入优化而已

#include <cstdio>
#include <iostream>
#pragma GCC optimize(3)
using namespace std;
int n,m,a[110000],ans[10],mini,minj,mink,tmp=0;
void read(int & p)
{
	p=0;int flag=1;char c=getchar();
	while(c<'0'||c>'9') {if(c=='-') flag=-1;c=getchar();}
	while(c>='0'&&c<='9')p=p*10+(c-'0'),c=getchar();
	p*=flag;
}
int check(int x,int y,int z)
{
	if(x+y>z && x+z>y && y+z>x)return 1;
	return 0;
}
void get_ans(int i,int j,int k)
{
	ans[3]=max(i,max(j,k));
	ans[1]=min(i,min(j,k));
	ans[2]=i+j+k-ans[3]-ans[1];
}
 int main()
 {
 	freopen("data.in","r",stdin);
// 	freopen("data.out","w",stdout);
 	read(n);//printf("%d$\n",n);
 	for(int i=1;i<=n;++i)read(a[i]);
 	read(m);
 	while(m--)
 	{
 		int opt=0;
 		read(opt);
 		if(opt%2==1)
 		{
 			int x,y;read(x);read(y);a[x]=y;//modify
 		}
 		else
 		{
 			tmp=0;ans[1]=ans[2]=ans[3]=0;
 			for(int k=3;k<=n;k++)
 				for(int j=2;j<k;j++)
 					for(int i=1;i<j;i++)
 						if(check(a[i],a[j],a[k]))
						{
							tmp++;
							get_ans(a[i],a[j],a[k]);
							i=j=k=(n+100);
						}
			if(tmp==0)printf("-1 -1 -1\n");//if(ans[1]==-1 && ans[2]==ans[3] && ans[2]==-1)
			else
			{
				for(int i=1;i<=3;++i)printf("%d ",ans[i]);
				printf("\n");
			}
 		}
 	}
 	return 0;
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值