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;
}