QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#261051#6639. Disk Treeucup-team1198#ML 31ms242712kbC++2013.2kb2023-11-22 17:38:182023-11-22 17:38:20

Judging History

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

  • [2023-11-22 17:38:20]
  • 评测
  • 测评结果:ML
  • 用时:31ms
  • 内存:242712kb
  • [2023-11-22 17:38:18]
  • 提交

answer

#include <bits/stdc++.h>

#define all(a) (a).begin(), (a).end()
#define sz(a) (int)(a).size()
#define pb push_back

using namespace std;

#define int int64_t

typedef long long ll;
typedef long double ld;
typedef pair<ld, ld> pld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

mt19937 rr(998244353);

void rs(vector<int>& v) {
    for (int i = 1; i < sz(v); ++i) {
        int j = rr() % (i + 1);
        swap(v[i], v[j]);
    }
}

struct pt {
    ll x, y;
    int id;
    pt() {}
    pt(ll x, ll y, int id = -1) : x(x), y(y), id(id) {}
    bool operator<(const pt& other) const {
        if (x != other.x) {
            return x < other.x;
        }
        return y < other.y;
    }
    pt operator-(const pt& other) const {
        return {x - other.x, y - other.y};
    }
};

ll cross(const pt& p, const pt& q) {
    return p.x * q.y - p.y * q.x;
}

ll dot(const pt& p, const pt& q) {
    return p.x * q.x + p.y * q.y;
}

struct triangle {
    int e[3];
    triangle(int a, int b, int c) {
        e[0] = a, e[1] = b, e[2] = c;
    }
    triangle() {}
};

const int nmax = 2e6;
const int emax = nmax * 3;

pii edges[emax];
int g[emax];
triangle triangles[nmax];
vector<pt> p;
int ptre = 0;
int ptr = 0;

int getOther(int v, int a, int b) {
    triangle& t = triangles[v];
    for (int i = 0; i < 3; ++i) {
        int j = t.e[i];
        int u = edges[j].first, v = edges[j].second;
        if (u != a && u != b) {
            return u;
        }
        if (v != a && v != b) {
            return v;
        }
    }
    assert(false);
}

int getId(int v, int a, int b) {
    triangle& t = triangles[v];
    for (int i = 0; i < 2; ++i) {
        int j = t.e[i];
        if (edges[j].first + edges[j].second == a + b) {
            return j;
        }
    }
    return t.e[2];
}

int getSide(int a, int u, int v) {
    assert(a != u && a != v && a >= 0);
    if (u >= 0 && v >= 0) {
        ll val = cross(p[a] - p[u], p[v] - p[u]);
        return (val > 0 ? 1 : (val == 0 ? 0 : -1));
    }
    if (u == -1 && v == -2) {
        return -1;
    }
    if (u == -2 && v == -1) {
        return 1;
    }
    int ans = (p[a] < p[max(u, v)] ? 1 : -1);
    if (u == - 1 || v == -2) {
        ans *= (-1);
    }
    return ans;
}

bool inside(int i, int a, int b = -3, int c = -1) {
    if (i < 0) {
        return false;
    }
    if (b == -3) {
        int t = a;
        int j = triangles[t].e[0];
        a = edges[j].first, b = edges[j].second;
        c = getOther(t, a, b);
    }
    int cnt = 0;
    if (a < 0) {
        ++cnt;
    }
    if (b < 0) {
        ++cnt;
    }
    if (c < 0) {
        ++cnt;
    }
    int arr[3];
    if (cnt >= 2) {
        arr[0] = -1, arr[1] = a + b + c + 3, arr[2] = -2;
    } else if (cnt == 0) {
        arr[0] = a;
        if (cross(p[b] - p[a], p[c] - p[a]) < 0) {
            arr[1] = b, arr[2] = c;
        } else {
            arr[1] = c, arr[2] = b;
        }
    } else if (cnt == 1) {
        if (b < 0) {
            swap(a, b);
        } else if (c < 0) {
            swap(a, c);
        }
        arr[0] = a;
        if (a == -1) {
            if (p[c] < p[b]) {
                arr[1] = b, arr[2] = c;
            } else {
                arr[1] = c, arr[2] = b;
            }
        } else {
            if (p[b] < p[c]) {
                arr[1] = b, arr[2] = c;
            } else {
                arr[1] = c, arr[2] = b;
            }
        }
    }
    
    for (int j = 0; j < 3; ++j) {
        int u = arr[j], v = arr[(j + 1) % 3];
        if (u < 0 && v < 0) {
            continue;
        }
        if (u >= 0 && v >= 0) {
            if (cross(p[i] - p[u], p[v] - p[u]) < 0) {
                return false;
            }
        } else if (u == -1) {
            if (p[v] < p[i]) {
                return false;
            }
        } else if (v == -1) {
            if (p[i] < p[u]) {
                return false;
            }
        } else if (u == -2) {
            if (p[i] < p[v]) {
                return false;
            }
        } else if (v == -2) {
            if (p[u] < p[i]) {
                return false;
            }
        }
    }
    
    return true;
}

bool onSegment(int i, int a, int b) {
    pt u = p[a] - p[i], v = p[b] - p[i];
    return cross(u, v) == 0 && dot(u, v) <= 0;
}

bool onEdge(int i, int id) {
    int u = edges[id].first, v = edges[id].second;
    if (u >= 0 && v >= 0) {
        return onSegment(i, u, v);
    }
    return false;
}

struct edgeInfo {
    int t[2];
    int pos[2];
    edgeInfo() {
        t[0] = t[1] = pos[0] = pos[1] = -1;
    }
    edgeInfo(int x, int y) {
        t[0] = x, pos[0] = y;
        t[1] = pos[1] = -1;
    }
};

edgeInfo info[emax];

void change(int e, int tOld, int t, int pos) {
    if (info[e].t[0] == tOld) {
        info[e].t[0] = t;
        info[e].pos[0] = pos;
    } else {
        info[e].t[1] = t;
        info[e].pos[1] = pos;
    }
}

bool inside(const pt& a, const pt& b, const pt& c, const pt& d) {
    pt u1 = a - c, v1 = b - c;
    pt u2 = a - d, v2 = b - d;
    return ld(abs(cross(u1, v1))) * dot(u2, v2) + ld(abs(cross(u2, v2))) * dot(u1, v1) < 0;
}

queue<int> qu;

int common;

void legalize() {
    while (!qu.empty()) {
        int id = qu.front();
        qu.pop();
        if (info[id].t[1] == -1) {
            continue;
        }
        int i, j, k, l;
        i = edges[id].first, j = edges[id].second;
        int t1 = info[id].t[0], t2 = info[id].t[1];
        k = getOther(t1, i, j), l = getOther(t2, i, j);
        int a = getId(t1, i, k);
        int b = getId(t1, j, k);
        int c = getId(t2, i, l);
        int d = getId(t2, j, l);
        bool flip = false;
        if (i < 0 || j < 0) {
            if (inside(i, j, k, l) || inside(j, i, k, l)) {
                continue;
            }
        } else {
            int sgn1 = getSide(i, k, l), sgn2 = getSide(j, k, l);
            if (sgn1 == 0 || sgn2 == 0 || sgn1 == sgn2) {
                continue;
            }
        }
        if (i < 0 || j < 0 || k < 0 || l < 0) {
            if (min(i, j) < min(k, l)) {
                flip = true;
            }
        } else {
            if (inside(p[i], p[j], p[k], p[l])) {
                flip = true;
            }
        }
        if (flip) {
            edges[ptre++] = {k, l};
            triangles[ptr++] = {ptre - 1, a, c};
            change(a, t1, ptr - 1, 1);
            change(c, t2, ptr - 1, 2);
            change(ptre - 1, -1, ptr - 1, 0);
            triangles[ptr++] = {ptre - 1, b, d};
            change(b, t1, ptr - 1, 1);
            change(d, t2 , ptr - 1, 2);
            change(ptre - 1, -1, ptr - 1, 0);
            g[t1 * 3] = ptr - 2;
            g[t1 * 3 + 1] = ptr - 1;
            g[t2 * 3] = ptr - 2;
            g[t2 * 3 + 1] = ptr - 1;
            
            if (common == k) {
                qu.push(c);
                qu.push(d);
            } else {
                qu.push(a);
                qu.push(b);
            }
        }
    }
}

ll dist2(const pt& a, const pt& b) {
    return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}

struct edge {
    int u, v;
    ll cost;
    bool operator<(const edge& other) const {
        return cost < other.cost;
    }
};

vector<int> parent;
vector<int> ssize;
vector<vector<int> > subtree;

vector<vector<int> > w;
vector<pii> zapr;

vector<array<int, 2>> solve(vector<array<int, 2>> pt_) {
    int n = pt_.size();
    
    memset(g, -1, sizeof(g));
    ptr = 0;
    ptre = 0;
    p.resize(n);
    
    vector<int> newId(n);
    for (int i = 0; i < n; ++i) {
        p[i].x = pt_[i][0];
        p[i].y = pt_[i][1];
        p[i].id = i;
    }
    
    sort(all(p));
    reverse(all(p));
    for (int i = 0; i < n; ++i) {
        newId[p[i].id] = i;
    }
    
    edges[ptre++] = {-1, 0};
    edges[ptre++] = {0, -2};
    edges[ptre++] = {-2, -1};
    triangles[ptr++] = {0, 1, 2};
    info[0] = {0, 0};
    info[1] = {0, 1};
    info[2] = {0, 2};
    
    vector<int> perm;
    for (int i = 1; i < n; ++i) {
        perm.pb(i);
    }
    rs(perm);
    
    for (int i = 0; i < sz(perm); ++i) {
        int v = 0;
        while (g[v * 3] != -1) {
            if (g[v * 3 + 2] == -1) {
                int id = g[v * 3];
                int j = triangles[id].e[0];
                int a = edges[j].first, b = edges[j].second;
                int c = getOther(id, a, b);
                int sgn1 = getSide(perm[i], a, b);
                int sgn2 = getSide(c, a, b);
                if (sgn1 == 0 || sgn1 == sgn2) {
                    v = id;
                } else {
                    v = g[v * 3 + 1];
                }
            } else {
                bool done = false;
                for (int z = 0; z + 1 < 3; ++z) {
                    int to = g[v * 3 + z];
                    if (inside(perm[i], to)) {
                        done = true;
                        v = to;
                        break;
                    }
                }
                if (!done) {
                    v = g[v * 3 + 2];
                }
            }
        }
        
        int on = -1;
        for (int z = 0; z < 3; ++z) {
            int j = triangles[v].e[z];
            if (onEdge(perm[i], j)) {
                on = j;
                break;
            }
        }
        
        if (on == -1) {
            int j = triangles[v].e[0];
            int a, b, c;
            a = edges[j].first, b = edges[j].second;
            c = getOther(v, a, b);
            
            edges[ptre++] = {perm[i], a};
            edges[ptre++] = {perm[i], b};
            edges[ptre++] = {perm[i], c};
            int k = ptre;
            
            triangles[ptr++] = {triangles[v].e[0], k - 2, k - 3};
            change(k - 2, -1, ptr - 1, 1);
            change(k - 3, -1, ptr - 1, 2);
            change(triangles[v].e[0], v, ptr - 1, 0);
            
            triangles[ptr++] = {getId(v, b, c), k - 1, k - 2};
            change(k - 1, -1, ptr - 1, 1);
            change(k - 2, -1, ptr - 1, 2);
            change(getId(v, b, c), v, ptr - 1, 0);
            
            triangles[ptr++] = {getId(v, c, a), k - 3, k - 1};
            change(k - 3, -1, ptr - 1, 1);
            change(k - 1, -1, ptr - 1, 2);
            change(getId(v, c, a), v, ptr - 1, 0);
            
            g[v * 3] = ptr - 1;
            g[v * 3 + 1] = ptr - 2;
            g[v * 3 + 2] = ptr - 3;
            
            for (int z = 0; z < 3; ++z) {
                qu.push(triangles[v].e[z]);
            }
        } else {
            int a = edges[on].first, b = edges[on].second;
            int u = info[on].t[1] + info[on].t[0] - v;
            int c = getOther(v, a, b);
            int d = getOther(u, a, b);
            edges[ptre++] = {perm[i], a};
            edges[ptre++] = {perm[i], b};
            edges[ptre++] = {perm[i], c};
            edges[ptre++] = {perm[i], d};
            
            int k = ptre;
            
            vector<int> vctx = {v, u};
            vector<int> vctz = {c, d};
            vector<int> vct = {a, b};
            
            for (int j = 0; j < 2; ++j) {
                int x = vctx[j];
                int z = vctz[j];
                for (int q = 0; q < 2; ++q) {
                    int id = getId(x, vct[q], z);
                    triangles[ptr++] = {k - 2 + j, k - 4 + q, id};
                    g[x * 3 + q] = ptr - 1;
                    change(id, x, ptr - 1, 2);
                    change(k - 4 + q, -1, ptr - 1, 1);
                    change(k - 2 + j, -1, ptr - 1, 0);
                }
            }
            
            qu.push(getId(v, a, c));
            qu.push(getId(v, c, b));
            qu.push(getId(u, a, d));
            qu.push(getId(u, b, d));
        }
        
        common = perm[i];
        legalize();
    }
    
    vector<array<int, 2>> ee;
    for (int v = 0; v < ptr; ++v) {
        if (g[v * 3] != -1) {
            continue;
        }
        for (int z = 0; z < 3; ++z) {
            int j = triangles[v].e[z];
            int u = edges[j].first, v = edges[j].second;
            if (u < 0 || v < 0) {
                continue;
            }
            ee.pb({p[u].id, p[v].id});
        }
    }
    return ee;
}

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);

    int n;
    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];
    }

    auto res = solve(pt);

    auto get_len = [&](int i, int j) {
        int dx = (pt[i][0] - pt[j][0]);
        int dy = (pt[i][1] - pt[j][1]);
        return dx * dx + dy * dy - r[i] * r[i] - 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;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 15ms
memory: 238732kb

input:

3
1 0 3
10 10 6
0 5 1

output:

YES
1 0 0 5
0 5 10 10

result:

ok answer = 1

Test #2:

score: 0
Accepted
time: 12ms
memory: 240872kb

input:

2
1 1 1
3 3 1

output:

YES
1 1 3 3

result:

ok answer = 1

Test #3:

score: 0
Accepted
time: 19ms
memory: 238820kb

input:

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

output:

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

result:

ok answer = 1

Test #4:

score: 0
Accepted
time: 4ms
memory: 238768kb

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
17 24 29 29
98 95 99 81
48 68 45 88
17 24 0 8
48 68 28 55
28 55 29 29
45 88 17 82
34 0 17 24
48 68 99 81

result:

ok answer = 1

Test #5:

score: 0
Accepted
time: 4ms
memory: 240876kb

input:

100
490 783 12
666 460 55
561 245 6
223 323 25
3 520 77
225 161 24
514 190 16
997 914 100
412 265 100
374 610 36
296 854 39
601 901 2
307 21 100
390 422 24
940 414 32
332 438 35
553 992 100
235 775 3
656 901 37
770 417 22
649 305 100
448 84 3
375 939 77
910 847 9
776 357 37
743 97 100
371 502 39
508...

output:

YES
770 417 749 401
809 794 811 693
255 263 267 249
448 84 447 40
95 208 76 226
255 263 195 241
951 132 975 153
412 265 422 163
833 250 837 286
137 156 133 115
601 901 553 992
899 204 964 284
32 773 81 790
563 635 533 734
787 237 833 250
160 703 235 775
448 84 482 132
769 474 846 495
865 52 897 76
9...

result:

ok answer = 1

Test #6:

score: 0
Accepted
time: 8ms
memory: 238824kb

input:

200
2948 9798 687
3897 647 35
3918 587 28
1262 2717 206
1315 9524 20
2381 305 1000
4344 6858 20
6234 8949 53
5168 4772 85
5044 6109 158
72 7670 132
7300 1213 837
5427 2263 1000
1785 3009 276
6136 1421 43
1629 5620 29
6445 9489 242
8443 3141 1000
4118 4307 63
1874 5238 291
1964 5785 73
7794 3934 18
3...

output:

YES
8808 4438 9278 4357
3897 647 3918 587
6125 9979 6062 9827
9598 2086 9940 2103
9881 5238 9965 5083
1756 8604 2704 8279
4946 6252 5044 6109
3427 769 3524 778
9434 2844 9514 2928
2981 8806 2975 8690
3881 5104 3074 4508
7018 8858 7259 8795
4344 6858 4160 6939
8791 6984 8868 7083
3731 790 3524 778
61...

result:

ok answer = 1

Test #7:

score: 0
Accepted
time: 23ms
memory: 238856kb

input:

300
42942 37079 222
49441 21821 1695
61023 31153 561
86630 26307 352
36940 78253 213
7841 81086 626
47425 22290 374
17694 68695 648
38259 64794 998
43599 46942 9662
9204 2816 1965
38652 83568 4057
4046 29001 1034
72591 63214 587
75984 64859 1112
70005 72177 576
34522 52126 652
56627 48785 1747
78820...

output:

YES
97653 50419 97975 50437
66345 83699 65601 83613
60208 7681 59945 7276
48642 86091 49759 86207
38589 38309 39086 38101
77511 65089 77469 64494
888 90680 649 91204
27731 53830 26217 53454
26217 53454 26810 54901
73117 73768 73572 71685
80020 86672 81812 87290
83090 83694 80629 84138
10530 82824 11...

result:

ok answer = 1

Test #8:

score: 0
Accepted
time: 8ms
memory: 239028kb

input:

1000
558504245 246224785 100000000
971981730 913036757 1821458
198791767 482624549 5998171
540520619 353988177 8924682
183178222 46223569 9859905
118485076 22129062 7497235
274928891 417171180 372954
230079763 468235825 289869
859092765 562864738 5551376
129036518 743777318 3969979
265158223 3092933...

output:

YES
741963125 249632478 749654230 245631243
299731657 172180704 299412197 169909676
744268608 502811255 749780007 500202962
719129758 362901109 718859247 362033902
637773206 344877200 637256234 344115816
506923531 47961807 496800989 56076643
802986231 620294429 801971917 620730756
781123049 61470226...

result:

ok answer = 1

Test #9:

score: 0
Accepted
time: 15ms
memory: 241580kb

input:

3000
442876143 334276354 3627270
526253918 947313397 2498956
566692880 229330019 4243066
497859604 658736917 13012787
315969653 65582717 1400013
394215653 932651144 1655676
58249045 973232518 860150
860773683 959388251 1594726
23803673 921365885 5926749
730359196 818999592 1521282
971839312 22835235...

output:

YES
390223036 962557192 395065091 961684986
278141533 211881820 279342544 211481944
403421973 160674394 388540598 156256536
20056939 793312760 23989584 790455936
370084895 524700222 370053752 526851391
83605887 493352547 174473105 535104153
264607878 236174923 264565844 235783795
799403583 515048991...

result:

ok answer = 1

Test #10:

score: 0
Accepted
time: 27ms
memory: 241852kb

input:

7000
601805179 978984160 464352
918208048 607538668 2214109
328147216 806677103 3901695
961794394 719893281 1114470
453816635 992288784 274949
778724702 692479905 1170018
169287513 886715521 576156
812072299 118324465 93778
726229729 150105801 3593039
368683874 642143790 1277375
40087476 151799345 4...

output:

YES
147132881 538273755 124294320 540614604
382625944 278906969 382515546 278713564
697337247 794958320 696633780 793111357
992855761 910338438 987588473 906458142
704574232 313018143 704454970 314676892
564617520 977122934 560644939 974602541
15064352 99341679 13828463 98607732
669134218 735724279 ...

result:

ok answer = 1

Test #11:

score: 0
Accepted
time: 31ms
memory: 242712kb

input:

10000
645 4710 5
1554 4072 7
6505 2760 1
6125 8212 11
9802 9537 3
6584 4356 6
1104 6649 23
4580 2623 20
3107 2460 1
4689 1662 2
7815 161 14
8718 3658 28
2900 63 15
1741 7296 44
8380 4608 50
2212 8514 4
7919 3069 17
1638 6057 3
504 9867 18
7869 8021 14
866 9239 5
3452 8042 4
9049 7222 4
4447 1004 5
9...

output:

YES
5031 7923 5034 7922
6548 2638 6545 2639
9183 8362 9182 8365
1872 6231 1873 6228
2420 5385 2423 5386
5944 3595 5945 3599
2936 3267 2937 3263
6972 4187 6971 4183
2542 2107 2542 2110
4845 6849 4847 6846
2028 8861 2031 8864
4626 3789 4628 3786
8 141 9 136
4404 4604 4399 4603
970 9908 972 9912
2416 9...

result:

ok answer = 1

Test #12:

score: -100
Memory Limit Exceeded

input:

100000
956095525 596102106 2
461544095 587257542 118
884402350 357055086 14228
547768407 186052059 263162
827807425 303694996 474924
692537425 44608243 131609
504660936 451030143 15134
207539367 899608364 20283
919236289 724317925 6
386476373 727023405 323
781914406 792770865 1064
411548762 2476126 ...

output:

YES
737182558 31629185 737205369 31606130
892696561 422861520 892145544 423239295
430638901 427457801 430648820 427446762
744488111 310224678 744495274 310246137
468728091 140185254 468718121 140164034
685322409 737069869 685305440 737074349
801637807 582451012 801681587 582450259
790259785 35554795...

result: