【CF 70D】Professor's task

【题意】

维护一个凸包,支持:
1、向凸包内新加入一个点;
2、询问某个点是否在当前凸包中。

【题解】

平时求凸包的时候,要用上极角排序。
那么,就排序吧。
然而,极点应该在哪里呢?
考虑到开头保证能给出一个没有退化的三角形,那么,就用这个三角形的重心作为极点。为了避免精度误差,就不除以 3 3 3了,改为将所有点的坐标乘 3 3 3。由于不求面积什么的,所以后面的操作就跟未乘 3 3 3的时候一样。
接下来先想如何判断点是否在凸包内。
考虑到如下情形(阴影部分为凸包):
在这里插入图片描述
显然,凸包上面的顶点均满足:
a 1 &lt; a 2 &lt; . . . &lt; a n ( a 表 示 极 点 序 序 号 ) a_1&lt;a_2&lt;...&lt;a_n(a表示极点序序号) a1<a2<...<ana
而且,若将这个点塞到凸包中,它的极点序序号也满足这个式子。所以,我们将点的前驱与后继求出来,然后用向量的叉积判断这个新加入点的凹凸性即可。
插入点的时候,先判断这个点是否在凸包内(因为如果在凸包内,这个点对原凸包是没有贡献的),然后把这个点插入这个凸包。
在这里插入图片描述
接着,找出这个点的前驱的前驱,判断凹凸性,一直往前面判断,直到找到一个凸点为止。后继也是一样的道理。
至于找前驱后继,可以用set/手写平衡树来搞。时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)
注意:可能有这种情况(标号为极角序序号,当前凸包中有m个顶点):
在这里插入图片描述
此时需特判即可
然而,计算几何说起来是一套一套的,写起来就是二楞二楞的了TAT,写了差不多半天才写出来

【代码】
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#define it set<point> :: iterator
using namespace std;
const double eps = 1e-7;
double ox, oy;
inline int dcmp(double x)
{
    if(fabs(x) < eps)
        return 0;
    return x < 0 ? -1 : 1;
}
struct point{
    double x, y, ang;
    point(){}
    point(double a, double b) : x(a), y(b) {ang = atan2(y - oy, x - ox);}
    point operator -(const point a) const{return point(x - a.x, y - a.y);}
    bool operator <(const point a) const {return dcmp(ang - a.ang) == 0 ? dcmp((x - ox) * (x - ox) - (a.x - ox) * (a.x - ox) + (y - oy) * (y - oy) - (a.y - oy) * (a.y - oy)) < 0 : dcmp(ang - a.ang) < 0;}
    bool operator ==(const point a)const{return dcmp(ang - a.ang) == 0 && dcmp((x - ox) * (x - ox) - (a.x - ox) * (a.x - ox) + (y - oy) * (y - oy) - (a.y - oy) * (a.y - oy)) == 0;}
}p[5];
set<point > s;
inline double cross(point a, point b) {return a.x * b.y - a.y * b.x;}
inline it l(it x) {
	if(x == s.begin()) x = s.end();
	x--;
	return x;
}
inline it r(it x) {
	x++;
	if(x == s.end()) x = s.begin();
	return x;
}
inline bool check_inside(point p)
{
    if(s.size() < 3)
        return 0;
    it a, b = s.lower_bound(p);
    if(b == s.end())
        b = s.begin();
    a = l(b);
    return dcmp(cross(p - *a, *b - p)) <= 0;
}
inline void push(point p)
{
    if(check_inside(p))
        return;
    s.insert(p);
    it pos = s.find(p), b = l(pos), a = l(b);
    while(dcmp(cross(*b - *a, p - *b)) <= 0)
        s.erase(b), b = a, a = l(a);
    a = r(pos), b = r(a);
    while(dcmp(cross(*a - p, *b - *a)) <= 0)
        s.erase(a), a = b, b = r(b);
}
int main()
{
    int n, t;
    double a, b;
    scanf("%d", &n);
    for(int i = 0; i < 3; i++)
    {
        scanf("%d%lf%lf", &t, &p[i].x, &p[i].y);
        ox += p[i].x, oy += p[i].y;
        p[i].x *= 3, p[i].y *= 3;
    }
    for(int i = 0; i < 3; i++)
        p[i] = point(p[i].x, p[i].y), s.insert(p[i]);
    n -= 3;
    while(n--)
    {
        scanf("%d%lf%lf", &t, &a, &b), a *= 3, b *= 3;
        if(t == 1)
            push(point(a, b));
        else
            puts(check_inside(point(a, b)) ? "YES" : "NO");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
EIA-364-70D是美国电子工业协会(EIA)发布的一个标准,涉及电子元器件的可靠性和可测试性。 EIA-364-70D标准主要涉及电子元器件的寿命和可靠性测试,以及对元器件进行可测试性评估的方法和要求。该标准旨在确保电子元器件在使用过程中具有足够的寿命和可靠性,同时也能够通过合适的测试手段进行有效地测试和验证。 根据EIA-364-70D标准,对电子元器件进行寿命测试需要考虑到元器件的使用环境和要求的可靠性水平。测试过程中通常会模拟元器件在不同的环境条件下的工作情况,例如温度、湿度、振动等。通过长时间的运行和观察,可以评估元器件在不同条件下的寿命特性,并确定其是否达到设计要求。 除了寿命测试,EIA-364-70D标准还着重于评估电子元器件的可测试性。可测试性是指元器件是否能够被有效地测试和验证其性能。标准要求元器件设计、制造和封装要考虑测试的需要,例如提供可访问的测试接口、确保信号传输的完整性、能够进行自动化测试等。 总之,EIA-364-70D是一个关于电子元器件寿命和可测试性的标准,通过对元器件进行寿命测试和可测试性评估,确保元器件在使用过程中具有足够的寿命和可靠性,并能够通过有效的测试手段进行验证。这有助于提高电子产品的可靠性,减少故障率,并有利于提高产品的质量和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值