QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#281618#6872. Magma Caveduongnc000AC ✓1727ms27680kbC++206.5kb2023-12-10 14:21:552023-12-10 14:21:55

Judging History

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

  • [2023-12-10 14:21:55]
  • 评测
  • 测评结果:AC
  • 用时:1727ms
  • 内存:27680kb
  • [2023-12-10 14:21:55]
  • 提交

answer

/*
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx2,fma,bmi,bmi2,sse4.2,popcnt,lzcnt")
*/

#include <bits/stdc++.h>
#define taskname ""
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define i64 long long
#define pb push_back
#define ff first
#define ss second
#define isz(x) (int)x.size()
using namespace std;

const int mxN = 4e5 + 5;
const int mod = 1e9 + 7;
const i64 oo = 1e18;

struct Edge {
    int u, v, w;
} e[mxN];

struct Node {
    int p, s[2];
    int rev, self, all;
};

int n, q;
bool has[mxN];

Node new_node(int id) {
    Node node;
    node.p = node.s[0] = node.s[1] = node.rev = 0;
    node.self = id;
    return node;
};

struct Fenwick {
    int n;
    vector<int> data;

    Fenwick() {}
    Fenwick(int n) : n(n), data(n + 1, 0) {}

    void add(int idx, int val) {
        for (; idx <= n; idx += idx & -idx)
            data[idx] += val;
    }

    int ask(int idx) {
        int res = 0;
        for (; idx; idx -= idx & -idx)
            res += data[idx];
        return res;
    }
};

struct DSU {
    int tot;
    vector<int> lab;

    DSU() {}
    DSU(int n) : tot(n), lab(n + 1, -1) {}

    int find(int v) {
        return lab[v] < 0 ? v : lab[v] = find(lab[v]);
    }

    bool merge(int u, int v) {
        u = find(u), v = find(v);
        if (u != v) {
            if (-lab[u] < -lab[v])
                swap(u, v);
            lab[u] += lab[v];
            lab[v] = u;
            --tot;
            return true;
        }
        return false;
    }
} d;

struct LinkCutTree {
    int type;
    Node tr[mxN];

    #define ls(x) tr[x].s[0]
    #define rs(x) tr[x].s[1]
    #define fa(x) tr[x].p

    Fenwick fenw;

    void init(int n, int q) {
        for (int i = 1; i <= n; ++i) {
            fa(i) = ls(i) = rs(i) = tr[i].rev = tr[i].self = 0;
        }
        fenw = Fenwick(q);
    }

    bool cmp(int a, int b) {
        if (!a) return false;
        if (!b) return true;
        return (e[a].w < e[b].w) ^ type;
    }

    void pushup(int u) {
        tr[u].all = tr[u].self;
        if (cmp(tr[ls(u)].all, tr[u].all)) tr[u].all = tr[ls(u)].all;
        if (cmp(tr[rs(u)].all, tr[u].all)) tr[u].all = tr[rs(u)].all;
    }

    int get(int x) {
        return x == rs(fa(x));
    }

    int isroot(int x) {
        return ls(fa(x)) != x && rs(fa(x)) != x;
    }

    void pushrev(int u) {
        swap(ls(u), rs(u));
        tr[u].rev ^= 1;
    }

    void pushdown(int u) {
        if (tr[u].rev) {
            if (ls(u)) pushrev(ls(u));
            if (rs(u)) pushrev(rs(u));
            tr[u].rev = 0;
        }
    }

    void rotate(int x) {
        int y = fa(x), z = fa(y), k = get(x);
        int w = tr[x].s[k ^ 1];
        if (!isroot(y)) tr[z].s[get(y)] = x;
        fa(x) = z;
        tr[y].s[k] = w, fa(w) = y;
        tr[x].s[k ^ 1] = y, fa(y) = x;
        pushup(y), pushup(x);
    }

    void pushall(int x) {
        if (!isroot(x)) pushall(fa(x));
        pushdown(x);
    }

    void splay(int x, int goal = 0) {
        for (pushall(x); !isroot(x); rotate(x)) {
            int y = fa(x);
            if (!isroot(y)) rotate(get(x) == get(y) ? y : x);
        }
    }

    void access(int x) {
        int z = x;
        for (int y = 0; x; y = x, x = fa(x))
            splay(x), rs(x) = y, pushup(x);
        splay(z);
    }

    void makeroot(int x) {
        access(x);
        pushrev(x);
    }

    int findroot(int x) {
        access(x);
        pushdown(x);
        while (ls(x)) pushdown(x = ls(x));
        splay(x);
        return x;
    }

    void split(int x, int y) {
        makeroot(x);
        access(y);
    }

    void link(int x, int y) {
        makeroot(x);
        if (findroot(y) != x) fa(x) = y;
    }

    void cut(int x, int y) {
        makeroot(x);
        if (findroot(y) == x && rs(x) == y && !ls(y)) {
            rs(x) = fa(y) = 0;
            pushup(x);
        }
    }

    void add_edge(int id) {
        tr[id + n] = new_node(id);
        auto &[u1, v1, w1] = e[id];
        if (d.find(u1) != d.find(v1)) {
            link(u1, id + n);
            link(v1, id + n);
            fenw.add(w1, 1);
        }
        else {
            split(u1, v1);
            int cur_id = tr[v1].all;
            if (cmp(cur_id, id)) {
                auto &[u2, v2, w2] = e[cur_id];
                cut(u2, cur_id + n);
                cut(v2, cur_id + n);
                fenw.add(w2, -1);
                link(u1, id + n);
                link(v1, id + n);
                fenw.add(w1, 1);
            }
        }
    }
} minimum_spanning_tree, maximum_spanning_tree;

void solve() {
    cin >> n >> q;
    minimum_spanning_tree.init(n, q);
    maximum_spanning_tree.init(n, q);
    d = DSU(n);
    fill(has + 1, has + q + 1, false);
    for (int i = 1; i <= q; ++i) {
        int op;
        cin >> op;
        if (op == 1) {
            auto &[u, v, w] = e[i];
            cin >> u >> v >> w;
            has[w] = true;
            minimum_spanning_tree.add_edge(i);
            maximum_spanning_tree.add_edge(i);
            d.merge(u, v);
        }
        else {
            int k, w;
            cin >> k >> w;
            if (!has[w] || d.tot != 1) {
                cout << "NO" << "\n";
            }
            else {
                int lower = maximum_spanning_tree.fenw.ask(w - 1) + 1;
                int upper = minimum_spanning_tree.fenw.ask(w);
                if (k >= lower && k <= upper) {
                    cout << "YES" << "\n";
                }
                else {
                    cout << "NO" << "\n";
                }
            }
        }
    }
}

signed main() {

#ifndef CDuongg
    if(fopen(taskname".inp", "r"))
        assert(freopen(taskname".inp", "r", stdin)), assert(freopen(taskname".out", "w", stdout));
#else
    freopen("bai3.inp", "r", stdin);
    freopen("bai3.out", "w", stdout);
    auto start = chrono::high_resolution_clock::now();
#endif

    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    minimum_spanning_tree.type = 1;
    maximum_spanning_tree.type = 0;
    int t = 1; cin >> t;
    while(t--) solve();

#ifdef CDuongg
   auto end = chrono::high_resolution_clock::now();
   cout << "\n"; for(int i = 1; i <= 100; ++i) cout << '=';
   cout << "\nExecution time: " << chrono::duration_cast<chrono::milliseconds> (end - start).count() << "[ms]" << endl;
#endif

}

详细

Test #1:

score: 100
Accepted
time: 1727ms
memory: 27680kb

input:

100
500 1999
1 112 419 318
1 419 208 1700
1 208 255 603
1 255 202 306
1 202 54 326
1 54 468 1506
1 468 23 856
1 23 90 758
1 90 271 1104
1 271 442 1900
1 442 441 19
1 441 378 1227
1 378 466 24
1 466 186 228
1 186 399 1387
1 399 288 297
1 288 144 1763
1 144 418 1896
1 418 217 673
1 217 281 1259
1 281 ...

output:

NO
NO
NO
NO
YES
NO
NO
YES
NO
NO
NO
NO
NO
YES
NO
YES
NO
YES
NO
NO
YES
YES
YES
YES
YES
YES
NO
YES
NO
YES
NO
NO
YES
NO
YES
YES
NO
NO
NO
NO
NO
YES
YES
NO
NO
NO
YES
YES
NO
NO
YES
NO
NO
NO
YES
YES
YES
YES
NO
NO
YES
NO
YES
NO
NO
NO
YES
NO
NO
NO
NO
YES
NO
YES
NO
NO
YES
NO
NO
NO
NO
NO
NO
NO
NO
NO
NO
NO
NO
YE...

result:

ok 321346 lines