QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#261122#6639. Disk Treeucup-team1198#WA 1ms7708kbC++206.5kb2023-11-22 18:03:092023-11-22 18:03:11

Judging History

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

  • [2023-11-22 18:03:11]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:7708kb
  • [2023-11-22 18:03:09]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;
#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define sz(x) ((int) (x).size())
#define all(x) x.begin(), x.end()
typedef long double ld;
typedef pair<int, int> pii;

using ll = long long;
 
const int maxn = 200100;
 
mt19937 rr(111);
ld rndEps() {
    return (ld(rr()) / rr.max() - 0.5) * 1e-7;
}
 
struct pt {
    ld x, y, z;
    int id;
    int pr, nx;
    bool inHull;
 
    pt() {}
 
    pt(ld x, ld y, ld z): x(x), y(y), z(z) {}
 
    pt operator-(const pt &p) const {
        return pt(x - p.x, y - p.y, z - p.z);
    }
 
    ld operator*(const pt &p) const {
        return x * p.x + y * p.y + z * p.z;
    }
 
    pt operator%(const pt &p) const {
        return pt(y * p.z - z * p.y,
                  z * p.x - x * p.z,
                  x * p.y - y * p.x);
    }
};
 
ostream &operator<<(ostream &out, pt &p) {
    return out << p.x << ' ' << p.y << ' ' << p.z;
}
 
istream &operator>>(istream &in, pt &p) {
    return in >> p.x >> p.y >> p.z;
}
 
//BEGIN_CODE
typedef tuple<int, int, int> Face;
 
int n;
pt p[maxn];
 
namespace Chan {
pt _p[maxn];
 
ld turny(int p1, int p2, int p3) {
    return (p[p2].x - p[p1].x) * (p[p3].y - p[p1].y) - 
        (p[p3].x - p[p1].x) * (p[p2].y - p[p1].y);
}
 
//replace y with z
ld turnz(int p1, int p2, int p3) {
    return (p[p2].x - p[p1].x) * (p[p3].z - p[p1].z) - 
        (p[p3].x - p[p1].x) * (p[p2].z - p[p1].z);
}
 
ld gett(int p1, int p2, int p3) {
    if (p1 == -1 || p2 == -1 || p3 == -1) {
        return 1e100;
    }
    ld ty = turny(p1, p2, p3);
    if (ty >= 0)
        return 1e100;
    else
        return turnz(p1, p2, p3) / ty;
}
 
void act(int i) {
    if (p[i].inHull) {
        p[p[i].nx].pr = p[i].pr;
        p[p[i].pr].nx = p[i].nx;
    } else {
        p[p[i].nx].pr = p[p[i].pr].nx = i;
    }
    p[i].inHull ^= 1;
}
 
ld updt(vector<int> &V) {
    if (V.empty()) {
        return 1e100;
    }
    int id = V.back();
    if (p[id].inHull)
        return gett(p[id].pr, p[id].nx, id);
    else
        return gett(p[id].pr, id, p[id].nx);
}
 
vector<int> buildHull(int l, int r) {
    if (l + 1 >= r) {
        p[l].pr = p[l].nx = -1;
        p[l].inHull = true;
        return {};
    }
    int mid = (l + r) / 2;
    auto L = buildHull(l, mid);
    auto R = buildHull(mid, r);
    reverse(all(L));
    reverse(all(R));
    int u = mid - 1, v = mid;
    while (true) {
        if (p[u].pr != -1 && 
                (turny(p[u].pr, u, v) <= 0))
            u = p[u].pr;
        else if (p[v].nx != -1 && 
                (turny(u, v, p[v].nx) <= 0))
            v = p[v].nx;
        else
            break;
    }
 
    ld t[6];
    t[0] = updt(L);
    t[1] = updt(R);
    vector<int> A;
    while (true) {
        t[2] = gett(p[u].pr, v, u);
        t[3] = gett(u, p[u].nx, v);
        t[4] = gett(u, p[v].pr, v);
        t[5] = gett(u, p[v].nx, v);
        ld nt = 1e100;
        int type = -1;
        forn (i, 6)
            if (t[i] < nt)
                nt = t[i], type = i;
        if (nt >= 1e100)
            break;
 
        if (type == 0) {
            act(L.back());
            if (L.back() < u)
                A.push_back(L.back());
            L.pop_back();
            t[0] = updt(L);
        } else if (type == 1) {
            act(R.back());
            if (R.back() > v)
                A.push_back(R.back());
            R.pop_back();
            t[1] = updt(R);
        } else if (type == 2) {
            A.push_back(u);
            u = p[u].pr;
        } else if (type == 3) {
            A.push_back(u = p[u].nx);
        } else if (type == 4) {
            A.push_back(v = p[v].pr);
        } else if (type == 5) {
            A.push_back(v);
            v = p[v].nx;
        }
    }
    assert(L.empty() && R.empty());
 
    p[u].nx = v, p[v].pr = u;
    for (int i = u + 1; i < v; ++i)
        p[i].inHull = false;
    for (int i = sz(A) - 1; i >= 0; --i) {
        int id = A[i];
        if (id <= u || id >= v) {
            if (u == id)
                u = p[u].pr;
            if (v == id)
                v = p[v].nx;
            act(id);
        } else {
            p[id].pr = u, p[id].nx = v;
            act(id);
            if (id >= mid)
                v = id;
            else
                u = id;
        }
    }
    return A;
}
 
ld dist2d(int i, int j) {
    pt p = _p[i] - _p[j];
    return hypotl(p.x, p.y);
}
 
vector<array<int, 2>> getEdges() {
    forn (i, n) {
        _p[i] = p[i];
        p[i].x += rndEps();
        p[i].y += rndEps();
        p[i].z += rndEps();
        p[i].id = i;
    }
    sort(p, p + n, [](const pt &a, const pt &b) {
                return a.x < b.x;
            });
 
    auto movie = buildHull(0, n);
    int i = 0;
    while (!p[i].inHull && i < n)
        ++i;
    assert(i < n);
    vector<array<int, 2>> es;
    while (i != -1 && p[i].nx != -1) {
        int u = p[i].id;
        int v = p[p[i].nx].id;
        es.push_back({u, v});
        i = p[i].nx;
    }
    for (int x: movie) {
        int id = p[x].id;
        int pid = p[p[x].pr].id;
        int nid = p[p[x].nx].id;
        if (!p[x].inHull) {
            es.push_back({id, pid});
            es.push_back({id, nid});
        } else {
            es.push_back({pid, nid});
        }
        act(x);
    }
 
    forn (i, n)
        p[i] = _p[i];
    return es;
}
} //namespace Chan
//END_CODE



const int MAXN = 2e5 + 100;

int dsu_p[MAXN], dsu_sz[MAXN];

int dsu_get(int v) {
    return v == dsu_p[v] ? v : dsu_p[v] = dsu_get(dsu_p[v]);
}

bool join(int u, int v) {
    u = dsu_get(u); v = dsu_get(v);
    if (u == v) return false;
    if (dsu_sz[u] < dsu_sz[v]) swap(u, v);;
    dsu_sz[u] += dsu_sz[v];
    dsu_p[v] = u;
    return true;
}

signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    cin >> n;
    vector<array<int, 2>> pt(n);
    vector<int> r(n);
    for (int i = 0; i < n; ++i) {
        cin >> pt[i][0] >> pt[i][1] >> r[i];
        p[i].x = pt[i][0];
        p[i].y = pt[i][1];
    }

    auto res = Chan::getEdges();

    auto get_len = [&](int i, int j) {
        ll dx = (pt[i][0] - pt[j][0]);
        ll dy = (pt[i][1] - pt[j][1]);
        return dx * dx + dy * dy - 1ll * r[i] * r[i] - 1ll * r[j] * r[j];
    };

    sort(res.begin(), res.end(), [&](array<int, 2> a, array<int, 2> b) {
        return get_len(a[0], a[1]) < get_len(b[0], b[1]);
    });

    iota(dsu_p, dsu_p + n, 0);
    fill(dsu_sz, dsu_sz + n, 1);

    cout << "YES\n";
    for (auto elem : res) {
        if (join(elem[0], elem[1])) {
            cout << pt[elem[0]][0] << " " << pt[elem[0]][1] << " ";
            cout << pt[elem[1]][0] << " " << pt[elem[1]][1] << "\n";
        }
    }

    return 0;
}

详细

Test #1:

score: 100
Accepted
time: 1ms
memory: 5720kb

input:

3
1 0 3
10 10 6
0 5 1

output:

YES
0 5 1 0
0 5 10 10

result:

ok answer = 1

Test #2:

score: 0
Accepted
time: 1ms
memory: 5604kb

input:

2
1 1 1
3 3 1

output:

YES
1 1 3 3

result:

ok answer = 1

Test #3:

score: 0
Accepted
time: 0ms
memory: 7708kb

input:

5
10 10 10
2 0 1
20 20 1
3 20 1
20 0 1

output:

YES
3 20 10 10
10 10 2 0
10 10 20 0
10 10 20 20

result:

ok answer = 1

Test #4:

score: -100
Wrong Answer
time: 0ms
memory: 7592kb

input:

10
29 29 2
28 55 10
99 81 4
17 82 10
45 88 10
48 68 10
0 8 10
98 95 10
34 0 10
17 24 10

output:

YES
29 29 17 24
98 95 99 81
17 24 0 8
45 88 17 82
17 24 34 0
45 88 98 95
17 82 29 29

result:

wrong output format Unexpected end of file - int32 expected