QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#640310#9316. BoxesLivinflyWA 64ms3944kbC++178.6kb2024-10-14 10:53:112024-10-14 10:53:12

Judging History

你现在查看的是最新测评结果

  • [2024-10-14 10:53:12]
  • 评测
  • 测评结果:WA
  • 用时:64ms
  • 内存:3944kb
  • [2024-10-14 10:53:11]
  • 提交

answer

// #pragma GCC optimize(2)

#include <bits/stdc++.h>

#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define mkp(x, y) make_pair((x), (y))
#define all(x) (x).begin(), (x).end()

using namespace std;

typedef long long LL;
// typedef double db;
typedef pair<int, int> PII;

// typedef LL db;
typedef LL db;
typedef pair<int, int> PII;

constexpr db inf = 1e18;
constexpr db eps = 0; // 0 当整数,1e-9
const db pi = acos(-1);

constexpr int sgn(db x) { return x < -eps ? -1 : x > eps; } // -1 0 1
constexpr int cmp(db x, db y) { return sgn(x - y); }
//三维计算几何
mt19937_64 rnd(time(0));
struct Point3 {
    db x, y, z;
    constexpr Point3(db _x = 0, db _y = 0, db _z = 0) : x(_x), y(_y), z(_z) {}
    constexpr Point3 operator+() const noexcept { return *this; }
    constexpr Point3 operator-() const noexcept { return Point3(-x, -y, -z); }
    constexpr Point3 operator+(const Point3& p) const {
        return Point3(x + p.x, y + p.y, z + p.z);
    }
    constexpr Point3 operator-(const Point3& p) const {
        return Point3(x - p.x, y - p.y, z - p.z);
    }
    constexpr Point3 operator*(const db& k) { return Point3(x * k, y * k, z * k); }
    constexpr Point3 operator/(const db& k) { return Point3(x / k, y / k, z / k); }
    // 点积
    db operator / (const Point3& r) const { return x * r.x + y * r.y + z * r.z; }
    // 叉积
    Point3 operator * (const Point3& r) const { return Point3(y * r.z - z * r.y, z * r.x - x * r.z, x * r.y - y * r.x); }
    constexpr Point3& operator+=(const Point3& p) {
        return x += p.x, y += p.y, z += p.z, *this;
    }
    constexpr Point3& operator-=(const Point3& p) {
        return x -= p.x, y -= p.y, z -= p.z, *this;
    }
    constexpr Point3& operator*=(const db& k) { return x *= k, y *= k, z *= k, *this; }
    constexpr Point3& operator/=(const db& k) { return x /= k, y /= k, z /= k, *this; }
    constexpr bool operator==(const Point3& r) const noexcept {
        return cmp(x, r.x) == 0 and cmp(y, r.y) == 0 and cmp(z, r.z) == 0;
    }
    constexpr bool operator <(const Point3& r)const noexcept {
        if (sgn(x - r.x))return x < r.x;
        if (sgn(y - r.y))return y < r.y;
        return z < r.z;
    }
    friend istream& operator>>(istream& is, Point3& p) { return is >> p.x >> p.y >> p.z; }
    friend ostream& operator<<(ostream& os, Point3 p) {
        return os << "(" << p.x << ", " << p.y << ", " << p.z << ")";
    }
    constexpr db dot(const Point3& r) const { return x * r.x + y * r.y + z * r.z; }
    constexpr Point3 cross(const Point3& r) const {
        return Point3(y * r.z - z * r.y, z * r.x - x * r.z, x * r.y - y * r.x);
    }
    void shake(double eps = 1e-12) { //微小扰动,去掉四点共面
        uniform_real_distribution<double> dist(-0.5, 0.5);
        // rand(-0.5, 0.5)
        // double Rand() { return rand() / (double)RAND_MAX; }
        // double reps() { return (Rand() - 0.5) * eps; }
        x += dist(rnd) * eps;
        y += dist(rnd) * eps;
        z += dist(rnd) * eps;
    }
};
db dot(const Point3& a, const Point3& b) { return a.dot(b); }
Point3 cross(const Point3& a, const Point3& b) { return a.cross(b); }
db square(Point3 p) { return dot(p, p); }
double len(Point3 p) { return sqrt(db(square(p))); }
Point3 unit(Point3 p) { return p / len(p); } // db <-> double 才能用
// volumn为六面体体积,volumn除以6为四面体组成的体积
db volumn0(Point3 a, Point3 b, Point3 c) { return dot(a, cross(b, c)); }
db volumn(Point3 a, Point3 b, Point3 c, Point3 d) { return dot(d - a, cross(b - a, c - a)); }
struct Line {
    Point3 a, b;
    Line(Point3 a_, Point3 b_) :a(a_), b(b_) {}
    Point3 normal() { return b - a; }
    Point3 pos(Point3 t) { return normal() * (t - a); }  // square len() == 0 在直线上
    Point3 pos(Line t) { return normal() * (t.normal()); } // square len() == 0 平行
    db dir(Line t) { return normal() / (t.normal()); }    // == 0 垂直,> 0 同向
    db dis_to_line(Point3 t) { return len(pos(t)) / len(normal()); }
    bool equal(Line t) { return dir(t) > 0 && sgn(square(pos(t.a))) == 0; }
    Point3 intersect(Line t) {  // 需要保证不平行,如果直线异面,返回的是俩直线的公垂线在 *this 直线上的垂足
        assert(sgn(square(pos(t))) != 0);
        return a + normal() * (t.pos(a) / pos(t)) / square(pos(t));
    }
};
struct Face {
    Point3 a, b, c;//逆时针方向
    Face(Point3 a_, Point3 b_, Point3 c_) :a(a_), b(b_), c(c_) {}
    Point3 normal() { return cross(b - a, c - a); }
    bool above(Point3 p) { return sgn(volumn(a, b, c, p)) > 0; }
    db pos(const Point3& t) { return dot(normal(), (t - a)); }   // > 0 严格在上方,== 0 在面上
    db pos(Line t) { return normal() / t.normal(); }   // == 0 和平面平行
    Point3 pos(Face t) { return normal() * t.normal(); } // square len() == 0 平行
    Point3 dir(Line t) { return normal() * t.normal(); } // square len() == 0 垂直
    db dir(Face t) { return normal() / t.normal(); }    // == 0 垂直, > 0 同向
    db dis_to_face(const Point3& t) { return pos(t) / len(normal()); }   // 在法向量上的投影
    bool equal(const Face& t) { return dir(t) > 0 && sgn(len(pos(t))) == 0 && sgn(pos(t.a)) == 0; }    // 面是否相等
};
typedef vector<Point3> vP;
typedef vector<vector<Point3>> vvP;
db area(vector<Face>p) { // 真实表面积要再/2
    db res = 0;
    for (auto t: p) res += len(t.normal());
    return res;
}
db volumn(vector<Face>p) { // 真实体积要再/6
    db res = 0;
    for (auto t: p) res += dot(cross(t.a, t.b), t.c);
    return res;
}
vector<Face> convex3d(vP p) { // 卷包裹
    auto q = p;
    // for (auto& x: p)x.shake(); // 是否保证无四点共面
    int n = p.size();
    for (int i = 0; i < n; i++) {
        if (p[i] < p[0]) swap(p[0], p[i]), swap(q[0], q[i]);
    }
    for (int i = 2; i < n; i++) {
        if ((p[i].x - p[0].x) * (p[1].y - p[0].y) > (p[i].y - p[0].y) * (p[1].x - p[0].x)) {
            swap(p[1], p[i]), swap(q[1], q[i]);
        }
    }
    vector<Face> res;
    set<PII> edge;
    //不允许出现四点共面
    if (n < 4) {
        return res;
    }
    function<void(int, int)>wrap = [&](int a, int b) {
        if (edge.count({ a,b }))return;
        int c = -1;
        for (int i = 0; i < n; i++) {
            if (i == a || i == b)continue;
            if (c == -1 || volumn(p[c], p[a], p[b], p[i]) > 0)c = i;
        }
        if (c == -1)return;
        res.emplace_back(q[a], q[b], q[c]);
        edge.insert({ a,b }), edge.insert({ b,c }), edge.insert({ c,a });
        wrap(c, b);
        wrap(a, c);
    };
    wrap(0, 1);
    return res;
}
vector<Face>convex3d2(vP p) { // 增量
    vector<Face>res;
    // for (auto& x : p)x.shake(); // 是否保证无四点共面
    if (p.size() < 4) return res;   // 不允许四点共面
    shuffle(p.begin(), p.end(), rnd);
    res.push_back({ p[0], p[1], p[2] });
    res.push_back({ p[2], p[1], p[0] });
    for (int i = 3; i < p.size(); i++) {
        vector<Face> tmp;
        set<pair<Point3, Point3>> edge;
        for (auto& x : res) {
            if (x.pos(p[i]) < 0) tmp.emplace_back(x);
            else edge.emplace(x.a, x.b), edge.emplace(x.b, x.c), edge.emplace(x.c, x.a);
        }
        for (auto& [x, y] : edge) {
            if (!edge.count({ y, x })) tmp.push_back({ x, y, p[i] });
        }
        swap(res, tmp);
    }
    return res;
}
// 凸包重心
Point3 centroid(vector<Face>p, Point3 G = {}, db sum = 0) {
    for (auto& x : p) {
        auto ng = x.a + x.b + x.c;
        db nv = dot(cross(x.a, x.b), x.c);
        sum -= nv;
        G -= ng * nv;
    }
    return G / 4 / sum;
}

void solve() {
    int n; cin >> n;
    vector<Point3> p(n);
    for(auto &[x, y, z]: p) cin >> x >> y >> z;
    set<Point3> st;
    LL ans = 0;
    while(p.size() >= 4) {
        auto ret = convex3d2(p);
        ans += volumn(ret);
        for(auto [x, y, z]: ret) {
            st.insert(x);
            st.insert(y);
            st.insert(z);
        }
        vector<Point3> t; t.reserve(n);
        for(auto x: p) {
            if(!st.count(x)) t.pb(x);
        }
        p.swap(t);
    }
    cout << ans << '\n';
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed;  // << setprecision(20); // double
    // freopen("i.txt", "r", stdin);
    // freopen("o.txt", "w", stdout);
    // time_t t1 = clock();
    int Tcase = 1;
    cin >> Tcase; // scanf("%d", &Tcase);
    while (Tcase--) 
        solve();
    // cout << "time: " << 1000.0 * (1.*(clock() - t1) / CLOCKS_PER_SEC) << "ms\n";
    return 0;
}

詳細信息

Test #1:

score: 100
Accepted
time: 0ms
memory: 3636kb

input:

2
4
0 0 1
0 0 2
0 1 1
1 1 1
10
2 6 3
2 9 0
2 1 0
3 7 3
0 5 6
10 9 2
4 4 2
8 5 2
4 6 9
6 7 5

output:

1
943

result:

ok 2 lines

Test #2:

score: 0
Accepted
time: 10ms
memory: 3728kb

input:

30
100
214848 13593 883915
404922 704679 762266
19696 348707 172137
204169 674312 980107
159743 683657 537795
913278 244484 331997
342255 150373 745862
822992 993127 812010
78019 523301 874868
508779 130959 577626
506563 15210 31018
302821 671498 135922
379735 258803 474373
387144 676958 499943
9009...

output:

8466306477510658674
7272556711339503943
7635348833914404146
8107228712222480162
8154398837331856360
7551703717471512369
8340343101157128252
7911868248459799324
7911957494280349996
8295429352750849603
8170150524727285883
7448641514858636645
8373196774630538132
7404986332777191754
7496214926512003280
...

result:

ok 30 lines

Test #3:

score: 0
Accepted
time: 3ms
memory: 3724kb

input:

300
10
284000 364959 249145
243447 261451 165064
884086 450907 263262
986606 115922 516435
550174 625062 491782
992985 764800 854837
992741 919628 758329
114851 373304 743149
236804 572126 522753
694056 863964 768484
10
328584 59621 865079
133943 928163 534857
746608 698892 195503
199343 568337 4820...

output:

803077918387863438
484728351097401010
1106436691630702280
544591678232219117
1068791025597242587
930320279051363466
977769839732812040
699051820151945692
1140525392772278038
1116781785107680980
844917700022644714
672066651386061967
638048751063849731
1258576451479348061
476673417837522259
8473170752...

result:

ok 300 lines

Test #4:

score: -100
Wrong Answer
time: 64ms
memory: 3944kb

input:

1
3000
413652 522034 362874
161444 14592 423619
276585 592939 402025
969689 188554 136993
462321 11911 652603
155677 401331 635931
339965 202216 204346
992462 357822 565008
886658 168024 940016
767608 638795 810396
137017 720592 591380
131999 195424 726856
127795 754489 391676
201652 890036 283312
2...

output:

4933347942154243019

result:

wrong answer 1st lines differ - expected: '60273580163282897867', found: '4933347942154243019'