训练日志

计算几何学习进入了一个瓶颈啊 = =

有些偏难的东西进展很缓慢 加上最近做题类型确实单一 导致比赛的时候经常写跪

所以打算慢慢进展计算几何内容 每天都做一些常规的水题

先说下计算几何的情况

进入了扫描线部分 和之前普通的矩形周长并啥的画风完全不同了

目前搞出来的东西也挺少

HDU 3124

给你一些平面上不相交的圆 圆上的点的最近距离

平面最近点对有固定套路 但是放到圆上还有半径 不能套用(但据说现场有人考最近点对的做法搞过去了?)

求最近距离 考虑二分 剩下的就是快速判断圆是否相交

我们考虑扫描线 如果是对圆的左右垂直切线离散

左侧加入集合 右侧从集合中删除 那么相交会在某个时刻 集合内的圆中产生

而当x左边满足相交条件 一定是一段y中产生交点

所以我们考虑对所有点y排序 按照上述规则假如set

在插入和删除时检查相切就可以了

仅在插入时检查是存在问题的

如hdu上给的

-10 20 1

0 0 10

30 40 39

答案应该是后两个圆产生的1 但是如果仅在插入时判断 圆1会干扰结果

在圆1删除时 2 3重新相邻 应再更新答案

HDU 3662

三维凸包上面的个数

模板题了

三维凸包是一种增量算法

首先找出四个不共面的顶点组成一个四面体

逐个插入点p

如果p在当前凸包内 凸包不改变

如果p在凸包外 那么所有能p“看见”的面都应该被更新

用有向体积来判断点与面的关系

记录所选的面(若干个三角形) 每条边对应的面(边有方向的)

时间复杂度O(n^2)的

好像明白了道理也不会写 然后就照着xiaotiantang学长的代码码了一发

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int N = 550;

struct Point{
    double x, y, z;
    Point(){}
    Point(double _, double __, double ___):
        x(_), y(__), z(___) {}
    Point operator - (const Point p) const{return Point (x - p.x, y - p.y, z - p.z);}
    Point operator + (const Point p) const{return Point (x + p.x, y + p.y, z + p.z);}
    Point operator / (const double p) const{return Point (x / p, y / p, z / p);}
    Point operator ^ (const Point p) const{return Point (y * p.z - z * p.y, z * p.x - x * p.z, x * p.y - y * p.x);}
    Point operator * (const double t) const{return Point(x * t, y * t, z * t);}
    double operator * (const Point p) const{return x * p.x + y * p.y + z * p.z;}
};

double abs(Point  p){return sqrt(p * p);}

struct ConvexHull3D{
    struct Facet{
        int a, b, c;
        bool flag;
    };
    int n;
    Point pt[N];
    int tri_num;
    Facet face[8 * N];
    int g[N][N];

    Point Cross(const Point & a, const Point & b, const Point & c){
        return (b - a) ^ (c - a);
    }

    double tri_area(Point a, Point b, Point c){
        return abs(Cross(c, a, b)) / 2;
    }

    double tetrahedron_volume(Point a, Point b, Point c, Point d){
        return (((b - a) ^ (c - a)) * (d - a)) / 6;
    }

    double dlcmp(Point & p, Facet & f){
        Point m = pt[f.b] - pt[f.a],
              n = pt[f.c] - pt[f.a],
              t = p - pt[f.a];
        return (m ^ n) * t;
    }

    void deal(int a, int b, int p){
        int f = g[a][b];
        Facet add;
        if(face[f].flag){
            if(dlcmp(pt[p], face[f]) > eps)
                dfs(p, f);
            else{
                add.a = b;
                add.b = a;
                add.c = p;
                add.flag = 1;
                g[p][b] = g[a][p] = g[b][a] = tri_num;
                face[tri_num ++] = add;
            }
        }
    }

    void dfs(int p, int now){
        face[now].flag = 0;
        deal(face[now].b, face[now].a, p);
        deal(face[now].c, face[now].b, p);
        deal(face[now].a, face[now].c, p);
    }

    bool same(int s, int t){
        Point & a = pt[face[s].a];
        Point & b = pt[face[s].b];
        Point & c = pt[face[s].c];
        bool res = fabs(tetrahedron_volume(a, b, c, pt[face[t].a])) < eps
                && fabs(tetrahedron_volume(a, b, c, pt[face[t].b])) < eps
                && fabs(tetrahedron_volume(a, b, c, pt[face[t].c])) < eps;
        return res;
    }

    void solve(){
        int i, j, tmp;
        Facet add;
        bool flag;
        tri_num = 0;
        if(n < 4) return;
        flag = 1;
        for(i = 1; i < n; i ++)
            if(abs((pt[0] - pt[1]) ^ (pt[1] - pt[i])) > eps){
                swap(pt[2], pt[i]);
                flag = 0;
                break;
            }
        if(flag) return;
        flag = 1;
        for(int i = 2; i < n; i ++){
            if(fabs( ((pt[0] - pt[1]) ^ (pt[1] - pt[2])) * (pt[0] - pt[i]) ) > eps){
                swap(pt[3], pt[i]);
                flag = 0;
                break;
            }
        }
        if(flag) return;
        flag = 1;
        for(int i = 3; i < n; i ++)
            if(abs(pt[0] - pt[i]) > eps){
                swap(pt[1], pt[i]);
                flag = 0;
                break;
            }
        if(flag) return;
        for(int i = 0; i < 4; i ++){
            add.a = (i + 1) % 4;
            add.b = (i + 2) % 4;
            add.c = (i + 3) % 4;
            add.flag = 1;
            if(dlcmp(pt[i], add) > 0)
                swap(add.b, add.c);
            g[add.a][add.b] = g[add.b][add.c] = g[add.c][add.a] = tri_num;
            face[tri_num ++] = add;
        }

        for(i = 4; i < n; i ++)
            for( j = 0; j < tri_num; j ++)
                if(face[j].flag && dlcmp(pt[i], face[j]) > eps){
                    dfs(i, j);
                    break;
                }

        tmp = tri_num;
        for(i = tri_num = 0; i < tmp; i ++)
            if(face[i].flag) face[tri_num ++] = face[i];
    }

    double area(){
        double res = 0;
        if(n == 3)
            res = abs(Cross(pt[0], pt[1], pt[2])) / 2;
        else if(!tri_num){
            for(int i = 0; i < n; i ++)
                res += abs(pt[i] ^ pt[(i + 1) % n]);
            res = fabs(res);
        }
        else{
            for(int i = 0; i < tri_num; i ++)
                res += tri_area(pt[face[i].a], pt[face[i].b], pt[face[i].c]);
        }
        return res;
    }

    double volume(){
        double res = 0;
        Point tmp(0, 0, 0);
        for(int i = 0; i < tri_num; i ++)
            res += tetrahedron_volume(tmp, pt[face[i].a], pt[face[i].b], pt[face[i].c]);
        return fabs(res);
    }

    Point get_center(){//重心
        Point res(0, 0, 0), o(0, 0, 0), p;
        double sum = 0, vol;
        for(int i = 0; i < tri_num; i ++){
            vol = tetrahedron_volume(o, pt[face[i].a], pt[face[i].b], pt[face[i].c]);
            sum += vol;
            p = (o + pt[face[i].a] + pt[face[i].b] + pt[face[i].c]) * vol / 4;
            res = res + p;
        }
        res = res / sum;
        return res;
    }

    int triangle_num(){
        return tri_num;
    }

    int polygon_num(){
        int i, j, res, flag;
        res = 0;
        for(i = 0; i < tri_num; i ++){
            flag = 1;
            for(j = 0; j < i; j ++)
                if(same(i, j)){
                    flag = 0;
                    break;
                }
            res += flag;
        }
        return res;
    }
};

ConvexHull3D hull;
double PFD(Point p, Point a, Point b, Point c){
    Point vec = (b - a) ^ (c - a);
    Point t = a - p;
    double tmp = (vec * t) / (abs(vec));
    return fabs(tmp);
}

int main(){
    //freopen("enwrap.in", "r", stdin);
    //freopen("enwrap.out", "w", stdout);
    scanf("%d", &hull.n);
    for(int i = 0; i < hull.n; i ++)
        scanf("%lf%lf%lf", &hull.pt[i].x, &hull.pt[i].y, &hull.pt[i].z);
    hull.solve();
    printf("%.6lf\n", hull.tri_num);
    return 0;
}

代码还是比较好理解的 自己实现估计会很麻烦 当成板子吧

还有一道题 atcoder 069 E

给你一个偶数长的排列 你每次可以取出相邻的两个元素 保持原来的顺序扔到另一个初始为空的队列的队首 直到原序列空

问你新队列字典序最小是什么

sb了一发 被潘学姐嘲笑 肯定会想着倒过来考虑 想每次找合法的最小从左到右放置起来

对于一个偶数长的串LR 肯定取一个奇数下标l为第一个 后面的偶数下标r为第二个

这样序列又被划分成三各偶数串 [L,l -1], [l +1,r - 1], [r + 1,R]递归下去 (相对的下标已经更新了 但每次都是奇数开头 偶数结尾)

每次找最小就可以了

这样会有一种拓扑关系 也有字典序最小的限制 所以 用优先队列维护 每次找最小用ST  可以做到nlogn

但是我太懒了 = = 就写了zkw nlog^2n 跑的也不慢

其他的题目就当是练手的。。。但是简单的题目也出现了可怕的错误= =

还是要通过平时多敲来避免啊

其实在看一个多边形嵌套的扫描线问题 但想不明白

也打算开随机化算法的部分了 不是很着急(大概)

平时水题常规题也要做 训练加油吧

时间: 2024-08-24 09:11:34

训练日志的相关文章

训练日志2

这几天主要是在打比赛 计算几何写了一些推公式的题 UVALive 4413 相当于按比例 构造出一种小三角形 想求原来的大三角形 这道题用到了 梅涅劳斯定理 链接 简单来说就是一条过三角形三边所在直线的直线 有 AD * BE * CF = BD * CE * AF 证明也比较简单 应用到这题就是由三条直线和三个小三角形得到三个方程 解出来对应比例就可以了 POJ 2208 给你四面体六条边 求体积 欧拉四面体公式 链接 写的时候也并没有用公式 直接建系 也是可以算的 UVA 11524 给你一

Object_detection-模型训练日志结果解析

日志展示 指标说明: AP值表示正确识别物体的个数占总识别出的物体个数的百分数 AR值表示正确识别物体的个数占测试集中物体的总个数的百分数 IoU值即生成的框/掩膜与数据集中的标准的面积之交处于面积之并 Area表示识别物体的尺寸,其中:small<32^2,32^2<medium<96^2 ,large>96^2 maxDets每个图像的最大检测阈值 [email protected][.5:.95](someone denoted [email protected][.5,.9

[训练日志] 7月22-31日

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC"; color: #454545 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Times New Roman"; color: #454545; min-height: 15.0px } span.s1 { } span.s2 { font: 12.0px "

[训练日志] 7月17-21日

codeforces 351C [构造一个n*m的括号序列,每个位置根据%n的情况(和)分别有花费,求最小费用] [考虑一般dp.有结论状态不会超过n.所以我们以n位为一块,用f[i][k][j]表示目前i位,前缀和最小为k,当前和为j的最小费用,预处理出从状态转移矩阵T.然后用min_plus矩阵加速T^m计算.] [状态不超过2n的证明:在刚到达2n的前一刻的前缀和一定>n,所以可以将之后和为负的块往前调整,使得状态不超过2n] [此题也可考虑倍增, F[k][i][j]表示2^k * n个

[训练日志] 7月14日

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 12.0px Helvetica; color: #454545 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 12.0px "PingFang SC"; color: #454545 } p.p3 { margin: 0.0px 0.0px 0.0px 0.0p

[训练日志] 7月13日

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "PingFang SC"; color: #454545 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; color: #454545 } p.p3 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: justify; font: 12.0px Helve

2018上海高校金马五校赛训练日志

solve  5(A  E  F  I  L) rank  77 水题总体没有很卡,但提升的题都没有思路,实力差距还是有的. 个人感觉出了的题都是铜牌及以下的难度. A Wasserstein Distance <qj> 思路: 已知两堆的值,我求出它们的差,如果是正数,说明原始堆要挪走一部分:否则,则要从别的堆移一部分过来. 不难证明,为了使花费最小,直接从左到右扫一遍便可,这样一定最优. 两个优先队列,存下标和差值.扫一遍就过了. B 合约数 C 序列变换 D  数字游戏 E  小Y吃苹果

2017 全国多校第十场 训练日志

solve 2(310 / 634) J题题意搞错一口大锅. dzcH题结论猜对了,只是树上二分图不用匈牙利算法,能换成更高效的写法. B Array Challenge 高斯消元 + 矩阵快速幂 H Monkeys 二分图结论 J Schedule 优先队列 <qj> 题意: 有n个任务,给你开始时间和结束时间,有无数台机器,每台机器可以在同一时间最多处理一个任务,并且开机之后,只能关一次机,不能中途关机又开机. 问至少需要多少机器,在这么多台机器的情况下,最少花费多少.(花费 = 每台机器

ACM-ICPC-Swiss-Subregional 2017 训练日志

solved 7 (2/59) A Chess #include<bits/stdc++.h> using namespace std; typedef long long ll; template<class T> inline void read(T &ret){ int sign=1; char c=getchar(); while(c!='-' && (c>'9'||c<'0'))c=getchar(); if(c=='-')sign=-