D. Pair Of Lines
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given n points on Cartesian plane. Every point is a lattice point (i. e. both of its coordinates are integers), and all points are distinct.
You may draw two straight lines (not necessarily distinct). Is it possible to do this in such a way that every point lies on at least one of these lines?
Input
The first line contains one integer n (1 ≤ n ≤ 105) — the number of points you are given.
Then n lines follow, each line containing two integers *x**i* and *y**i* (|xi|, |yi| ≤ 109)— coordinates of i-th point. All n points are distinct.
Output
If it is possible to draw two straight lines in such a way that each of given points belongs to at least one of these lines, print YES. Otherwise, print NO.
Examples
input
Copy
50 00 11 11 -12 2
output
Copy
YES
input
Copy
50 01 02 11 12 3
output
Copy
NO
Note
In the first example it is possible to draw two lines, the one containing the points 1, 3 and 5, and another one containing two remaining points.
题意:
给你n个坐标点
问你能不能画两条直线,使所有的点都落在直线上。
(两条直线可以重合)。
思路:
n<=4 直接输出YES
n>=5 时,我们这样考虑:
如果这n个点是满足条件的。
那么两条线上点数中较大的那一个(称为L1)一定大于等于n/2
所以我们可以随机从n个点中选择2个点。
这两点同时落在L1上的概率为\(1/4\)
所以如果这n个点满足条件,我们只需要随机大概4次就可以找到那两条线。
4次只是期望值,N的数据范围是\(1e5\) 所以我们可以随机50次以上,这样更稳。
关于随机到2个点,
我们扫一遍数组,把所有不在这2个确定的直线上的都扔在一个vector里存着。
然后我们再判断vector中所有点是否在同一个直线上。如果有满足条件的就结束随机,输出Yes。
代码:
#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
// #define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
inline void getInt(int *p);
const int maxn = 100010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
const double eps = 1e-6;
int sgn(double x)
{
if (fabs(x) < eps) { return 0; }
if (x < 0) { return -1; }
else { return 1; }
}
struct Point {
ll x, y;
Point() {}
Point(double _x, double _y)
{
x = _x; y = _y;
}
void input()
{
cin >> x >> y;
}
Point operator -(const Point &b)const
{
return Point(x - b.x, y - b.y);
}
// 111 / 179
//叉积
double operator ^(const Point &b)const
{
return x * b.y - y * b.x;
}
//点积
double operator *(const Point &b)const
{
return x * b.x + y * b.y;
}
//绕原点旋转角度 B(弧度值),后 x,y 的变化
void transXY(double B)
{
double tx = x, ty = y;
x = tx * cos(B) - ty * sin(B);
y = tx * sin(B) + ty * cos(B);
}
};
int n;
Point a[maxn];
std::vector<int> p;
int main()
{
//freopen("D:\\code\\text\\input.txt","r",stdin);
//freopen("D:\\code\\text\\output.txt","w",stdout);
gbtb;
cin >> n;
repd(i, 1, n) {
a[i].input();
}
if (n <= 4) {
cout << "YES" << endl;
return 0;
}
int id1, id2;
mt19937 rnd(time(0));
int isok = 0;
repd(rp, 1, 100) {
p.clear();
id1 = rnd() % n + 1;
do {
id2 = rnd() % n + 1;
} while (id2 == id1);
repd(i, 1, n) {
if (i == id1 || id2 == i) {
continue;
}
if (((a[id2] - a[id1]) ^ (a[i] - a[id1])) != 0) {
p.push_back(i);
}
}
int flag = 1;
for (int i = 2; i < sz(p); ++i) {
if (((a[p[1]] - a[p[0]]) ^ (a[p[i]] - a[p[0]])) != 0) {
flag = 0;
break;
}
}
if (flag) {
isok = 1;
// chu(id1);
// chu(id2);
break;
}
}
if (isok) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
return 0;
}
inline void getInt(int *p)
{
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
} else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}