①:有结论:面积最大的三角形即为所求
证明:若有点在面积最大的三角形对应
“
A
n
t
i
c
o
m
p
l
e
m
e
n
t
a
r
y
T
r
i
a
n
g
l
e
”
“Anticomplementary Triangle”
“AnticomplementaryTriangle”之外,一定能取得更大的面积。如下图:
②:
O
(
n
)
O(n)
O(n)时间内找到这个三角形
1.
O
(
n
2
)
1.O(n^2)
1.O(n2)显然,因为
i
,
j
i,j
i,j固定后,面积关于坐标k的函数一定是单峰函数,
j
,
k
j,k
j,k可以当双指针做,复杂度少一个
n
n
n
2.
2.
2.假如依然按双指针做,固定
i
,
j
0
i,j0
i,j0时找到最优的
k
0
k0
k0,固定
i
,
j
1
i,j1
i,j1时找到最优的
k
1
k1
k1,固定
i
,
j
2
i,j2
i,j2时找到最优的
k
2
k2
k2,并且固定
i
,
k
0
i,k0
i,k0时找到的最优解是
j
2
j2
j2
现证明
S
(
i
,
j
1
,
k
1
)
<
S
(
i
,
j
2
,
k
2
)
S(i,j1,k1)<S(i,j2,k2)
S(i,j1,k1)<S(i,j2,k2)
根据定义可列出如下不等式:
S
(
i
,
j
1
,
k
0
)
<
S
(
i
,
j
2
,
k
0
)
<
S
(
i
,
j
2
,
k
1
)
<
S
(
i
,
j
2
,
k
2
)
S(i,j1,k0)<S(i,j2,k0)<S(i,j2,k1)<S(i,j2,k2)
S(i,j1,k0)<S(i,j2,k0)<S(i,j2,k1)<S(i,j2,k2)
满足
S
(
i
,
j
1
,
k
0
)
<
S
(
i
,
j
2
,
k
0
)
S(i,j1,k0)<S(i,j2,k0)
S(i,j1,k0)<S(i,j2,k0) 的情况下,图形如下所示,故可得到另一个不等式:
S
(
i
,
j
1
,
k
1
)
<
S
(
i
,
j
2
,
k
1
)
S(i,j1,k1)<S(i,j2,k1)
S(i,j1,k1)<S(i,j2,k1)
得证
原本是
j
j
j依次枚举,
k
k
k双指针跳转,这个结论可得到
j
,
k
j,k
j,k绑定,
i
i
i和
j
,
k
j,k
j,k的结合体做双指针,复杂度
O
(
n
)
O(n)
O(n)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+3;
struct point{
int x,y;
}p[N];
#define gc getchar
inline int rd(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=x*10+(ch^48);
return x*fl;
}
int cross(point p0,point p1,point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int li,lj,lk,n,i;
#define upd if(tmp>ans)ans=tmp,li=i,lj=j,lk=k;
void rotate(){
int ans=0;
p[n]=p[0];
for (int i=0,j=1,k=2;i<n;i++){
while (1){
int tmp,jj=j,kk=k;
while ((tmp=cross(p[i],p[j],p[k]))<cross(p[i],p[j],p[k+1])) k=(k==n-1?0:k+1);
upd
while ((tmp=cross(p[i],p[j],p[k]))<cross(p[i],p[j+1],p[k])) j=(j==n-1?0:j+1);
upd
if (j==jj && k==kk) break;
}
}
}
signed main(){
n=rd();
for (i=0;i<n;i++) p[i].x=rd(),p[i].y=rd();
rotate();
printf("%lld %lld %lld",li+1,lj+1,lk+1);
}
其实还可以类似 j j j的证法证一证 i i i,三个数一起循环看起来也更优美一点,代码如下:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+3;
struct point{
int x,y;
}p[N];
#define gc getchar
inline int rd(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=x*10+(ch^48);
return x*fl;
}
int cross(point p0,point p1,point p2){
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int li,lj,lk,n,i;
#define upd if(tmp>ans)ans=tmp,li=i,lj=j,lk=k;
void rotate(){
int ans=0;
p[n]=p[0];
int i=0,j=1,k=2;
bool fl=0;
while (k && !fl){
int ii=i,jj=j,kk=k,tmp;
while((tmp=cross(p[i],p[j],p[k]))<cross(p[i],p[j],p[k+1]))
if (k==n-1) fl=1,k=0;
else k++;
upd
while((tmp=cross(p[i],p[j],p[k]))<cross(p[i],p[j+1],p[k])) j=(j==n-1?0:j+1);
upd
while((tmp=cross(p[i],p[j],p[k]))<cross(p[i+1],p[j],p[k])) i=(i==n-1?0:i+1);
upd
if (i==ii && j==jj && k==kk) k=(k==n-1?0:k+1);
}
}
signed main(){
n=rd();
for (i=0;i<n;i++) p[i].x=rd(),p[i].y=rd();
rotate();
printf("%lld %lld %lld",li+1,lj+1,lk+1);
}