CF1019D

Posted king-george

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1019D相关的知识,希望对你有一定的参考价值。

题意

给平面上 (n) 个无三点共线和重点的点。
问是否存在三个点构成面积为 (S) 的三角形。

(3 leq n leq 2000, 1 leq S leq 2 cdot 10^{18}, -10^9 leq x, y leq 10^9)

做法1

求出两两叉积然后暴力 (O(n^3)) 枚举,枚举的时候注意最内层用 register,并且前两层算出的值与S做差存在变量中常数就小了。

做法2

将两两连线产生的直线极角排序,依次考虑以每条边为底是否存在三角形。
如果能维护出其余点关于该斜率直线 (kx + b)(b) 的顺序,则可以通过二分解决。
按极角顺序依次扫描,扫完两点连线的一条直线之后只用交换这两点的顺序,可以证明其余点之间的相对位置不变。
时间复杂度 (O(n^2 log n))

代码

#include <bits/stdc++.h>

#ifdef DEBUG
#define debug(...) fprintf(stderr, __VA_ARGS__)
#else
#define debug(...)
#endif

#ifdef __WIN32
#define LLFORMAT "I64"
#define Rand() ((rand() << 15) + rand())
#else
#define LLFORMAT "ll"
#define Rand() (rand())
#endif

using namespace std;

const int maxn = 2010;

struct point {
    int x, y;

    point() {}
    point(int x, int y): x(x), y(y) {}
} a[maxn];

point operator - (const point &a, const point &b) { return point(a.x - b.x, a.y - b.y); }
long long det(const point &a, const point &b) { return (long long) a.y * b.x - (long long) a.x * b.y; }

int n, rnk[maxn], p[maxn];
long long S;
vector<pair<point, pair<int, int> > > b;

int main() {
    scanf("%d%"LLFORMAT"d", &n, &S); S <<= 1;
    for (int i = 1; i <= n; ++i) {
        int x, y;
        scanf("%d%d", &x, &y);
        a[i] = point(x, y);
        rnk[i] = p[i] = i;
    }
    sort(a + 1, a + n + 1, [&](point s, point t) {
            return s.y == t.y ? s.x < t.x : s.y < t.y;
            });
    for (int i = 1; i <= n; ++i) for (int j = i + 1; j <= n; ++j) b.push_back(make_pair(a[j] - a[i], make_pair(i, j)));
    sort(b.begin(), b.end(), [&](pair<point, pair<int, int> > a, pair<point, pair<int, int> > b) {
            return det(a.first, b.first) < 0;
            });
    for (int k = 0; k < b.size(); ++k) {
        int i = b[k].second.first, j = b[k].second.second, lb, rb;
        lb = 1, rb = rnk[i] - 1;
        while(lb <= rb) {
            int mid = lb + rb >> 1, k = p[mid];
            long long s = det(a[i], a[j]) + det(a[j], a[k]) + det(a[k], a[i]);
            if(s < S) rb = mid - 1;
            else if(s == S) { printf("Yes
%d %d
%d %d
%d %d
", a[i].x, a[i].y, a[j].x, a[j].y, a[k].x, a[k].y); return 0; }
            else lb = mid + 1;
        }
        lb = rnk[i] + 1, rb = n;
        while(lb <= rb) {
            int mid = lb + rb >> 1, k = p[mid];
            long long s = det(a[i], a[j]) + det(a[j], a[k]) + det(a[k], a[i]);
            if(s < S) lb = mid + 1;
            else if(s == S) { printf("Yes
%d %d
%d %d
%d %d
", a[i].x, a[i].y, a[j].x, a[j].y, a[k].x, a[k].y); return 0; }
            else rb = mid - 1;
        }
        swap(p[rnk[i]], p[rnk[j]]);
        swap(rnk[i], rnk[j]);
    }
    puts("No");
    return 0;
}




以上是关于CF1019D的主要内容,如果未能解决你的问题,请参考以下文章

cf 模拟

CF1435 游记

无法解析符号 c882c94be45fff9d16a1cf845fc16ec5

本人想学习破解技术但是看不懂反汇编代码!求助!!

微信小程序代码片段

VSCode自定义代码片段——CSS选择器