求助 马蜂优良 TLE11,线段树合并+并查集
查看原帖
求助 马蜂优良 TLE11,线段树合并+并查集
802813
rqrqwerwq楼主2024/8/5 11:33
    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    using ld = long double;

    #define pb push_back

    int mod = 998244353;
    ll INF = (ll)1e18;

    template<typename T>
    T chmax(T a, T b) {
        return a > b ? a : b;
    }

    template<typename T>
    T chmin(T a, T b) {
        return a > b ? b : a;
    }

    const int N = (int)1e6 + 1;

    struct DSU{
        vector<int> node, size;
     
        DSU(){}
        DSU(int n){
            init(n);
        }
     
        void init(int n){
            node.resize(n);
            size.resize(n);
     
            for(int i = 0; i < n; i++){
                node[i] = i;
                size[i] = 1;
            }
        }
     
        int find(int x){
            return x == node[x] ? x : node[x] = find(node[x]);
        }
     
        void erase(int x){
            size[find(x)] -= 1;
            node[x] = x;
        }
     
        void relocate(int x, int y){ //can't be root
            int dx = find(x), dy = find(y);
            if(dx == dy){
                return;
            }
            node[x] = dy;
            size[dx] -= 1;
            size[dy] += 1;
        }
     
        int set(int x, int y){
            return find(x) == find(y);
        }
     
        int merge(int x, int y){
            x = find(x);
            y = find(y);
            if(x == y){
                return 0;
            }
     
            size[x] += size[y];
            node[y] = x;
            return 1;
        }
     
        int heuristic_merge(int x, int y){ 
            x = find(x);
            y = find(y);
            if(size[x] < size[y]){
                swap(x, y);
            }
            return merge(x, y);
        }
     
        int get(int x){
            return size[find(x)];
        }
    };

    template<class Operation>
    struct SegTree{
        const ll n, len;
        ll pos, root;
     
        struct Node {
            ll l, r;
            Operation op;
        };
     
        vector<Node> f;
     
        SegTree(ll n, ll len) : n(n), len(len), f(4 << __lg(n)), pos(0), root(0){}
     
        void pushup(ll u) {
            f[u].op = f[f[u].l].op + f[f[u].r].op;
        }
     
        void update(ll &u, ll l, ll r, ll x, const Operation &v){
            if(!u){
                u = ++pos;
                f[u].op = {};
                f[u].l = f[u].r = 0;
            }
            if(l == r){
                f[u].op = v; //也许会变
                return;
            }
            ll m = (l + r) >> 1;
            if(x <= m) {
                update(f[u].l, l, m, x, v);
            }
            else{
                update(f[u].r, m + 1, r, x, v);
            }

            pushup(u);
        }
     
        void update(ll &root, ll u, const Operation &v){
            update(root, 1, len, u, v);
        }

        void modify(ll u, ll v){
            f[u].op.sum = f[v].op.sum;
            f[u].op.cnt = f[v].op.cnt;
        }

        ll merge(ll u, ll v, ll l, ll r){
            if(!u){
                return v;
            }
            if(!v){
                return u;
            }
            if(l == r){
                modify(u, v);
                return u;
            }

            ll m = (l + r) >> 1;
            f[u].l = merge(f[u].l, f[v].l, l, m);
            f[u].r = merge(f[u].r, f[v].r, m + 1, r);
            pushup(u);
            return u;
        }

        Operation query(ll u, ll l, ll r, ll x, ll y){
            if(!u){
                return {};
            }
            if(x <= l && r <= y) {
                return f[u].op;
            }
     
            ll m = (l + r) >> 1;
            Operation cur;
            if(x <= m) {
                cur = query(f[u].l, l, m, x, y);
            }
            if(y > m) {
                cur = cur + query(f[u].r, m + 1, r, x, y);
            }
            return cur;
        }
     
        Operation query(ll &root, ll l, ll r){
            return query(root, 1, len, l, r);
        }
    };

    //预处理根

    struct Operation{ 
        ll sum, cnt;

        Operation(ll p = 0){
            if(p){
                sum = p;
                cnt = 1;
            }
            else{
                sum = 0;
                cnt = 0;
            }
        }
    };
     
    Operation operator+(Operation a, Operation b){
        Operation c;
        if(!a.cnt) return b;
        c.sum = a.sum + b.sum;
        c.cnt = a.cnt + b.cnt;
        return c;
    }

    void solve(){
        int n, m;
        cin >> n >> m;

        ll a[n + 1], root[n + 1];
        for(int i = 1; i <= n; i++){
            cin >> a[i];
            root[i] = i;
        }

        SegTree<Operation> tr(N, n);
        DSU dsu(N);
        tr.pos = n;

        for(int i = 1; i <= n; i++){
            tr.update(root[i], a[i], {i});
        }

        for(int i = 1; i <= m; i++){
            int u, v;
            cin >> u >> v;

            if(dsu.set(u, v)) continue;

            u = dsu.find(u), v = dsu.find(v);
            if(dsu.get(u) >= dsu.get(v)){
                tr.merge(u, v, 1, n);
            }
            else{
                tr.merge(v, u, 1, n);
            }
            dsu.heuristic_merge(u, v);
        }

        int q;
        cin >> q;

        for(int i = 1; i <= q; i++){
            char op;
            cin >> op;

            int x, k;
            cin >> x >> k;

            if(op == 'Q'){
                int l = 1, r = n + 1;
                x = dsu.find(x);

                while(l < r){
                    int m = l + r >> 1;
                    if(tr.query(root[x], 1, m).cnt >= k) r = m;
                    else l = m + 1;
                }

                auto qwq = tr.query(root[x], 1, l);

                if(qwq.cnt < k || qwq.cnt > k){
                    cout << -1 << endl;
                }
                else{
                    cout << tr.query(root[x], l, l).sum << endl;
                }
            }
            else{
                if(dsu.set(x, k)) continue;
                x = dsu.find(x), k = dsu.find(k);

                if(dsu.get(x) >= dsu.get(k)){
                    tr.merge(root[x], root[k], 1, n);
                }
                else{
                    tr.merge(root[k], root[x], 1, n);
                }
                dsu.heuristic_merge(x, k);
            }
        }
    }

    signed main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cout.tie(0);

        int t = 1;
        // cin >> t;

        while (t--) {
            solve();
        }

        return 0;
    }
```[]()```cpp
    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    using ld = long double;

    #define pb push_back

    int mod = 998244353;
    ll INF = (ll)1e18;

    template<typename T>
    T chmax(T a, T b) {
        return a > b ? a : b;
    }

    template<typename T>
    T chmin(T a, T b) {
        return a > b ? b : a;
    }

    const int N = (int)1e6 + 1;

    struct DSU{
        vector<int> node, size;
     
        DSU(){}
        DSU(int n){
            init(n);
        }
     
        void init(int n){
            node.resize(n);
            size.resize(n);
     
            for(int i = 0; i < n; i++){
                node[i] = i;
                size[i] = 1;
            }
        }
     
        int find(int x){
            return x == node[x] ? x : node[x] = find(node[x]);
        }
     
        void erase(int x){
            size[find(x)] -= 1;
            node[x] = x;
        }
     
        void relocate(int x, int y){ //can't be root
            int dx = find(x), dy = find(y);
            if(dx == dy){
                return;
            }
            node[x] = dy;
            size[dx] -= 1;
            size[dy] += 1;
        }
     
        int set(int x, int y){
            return find(x) == find(y);
        }
     
        int merge(int x, int y){
            x = find(x);
            y = find(y);
            if(x == y){
                return 0;
            }
     
            size[x] += size[y];
            node[y] = x;
            return 1;
        }
     
        int heuristic_merge(int x, int y){ 
            x = find(x);
            y = find(y);
            if(size[x] < size[y]){
                swap(x, y);
            }
            return merge(x, y);
        }
     
        int get(int x){
            return size[find(x)];
        }
    };

    template<class Operation>
    struct SegTree{
        const ll n, len;
        ll pos, root;
     
        struct Node {
            ll l, r;
            Operation op;
        };
     
        vector<Node> f;
     
        SegTree(ll n, ll len) : n(n), len(len), f(4 << __lg(n)), pos(0), root(0){}
     
        void pushup(ll u) {
            f[u].op = f[f[u].l].op + f[f[u].r].op;
        }
     
        void update(ll &u, ll l, ll r, ll x, const Operation &v){
            if(!u){
                u = ++pos;
                f[u].op = {};
                f[u].l = f[u].r = 0;
            }
            if(l == r){
                f[u].op = v; //也许会变
                return;
            }
            ll m = (l + r) >> 1;
            if(x <= m) {
                update(f[u].l, l, m, x, v);
            }
            else{
                update(f[u].r, m + 1, r, x, v);
            }

            pushup(u);
        }
     
        void update(ll &root, ll u, const Operation &v){
            update(root, 1, len, u, v);
        }

        void modify(ll u, ll v){
            f[u].op.sum = f[v].op.sum;
            f[u].op.cnt = f[v].op.cnt;
        }

        ll merge(ll u, ll v, ll l, ll r){
            if(!u){
                return v;
            }
            if(!v){
                return u;
            }
            if(l == r){
                modify(u, v);
                return u;
            }

            ll m = (l + r) >> 1;
            f[u].l = merge(f[u].l, f[v].l, l, m);
            f[u].r = merge(f[u].r, f[v].r, m + 1, r);
            pushup(u);
            return u;
        }

        Operation query(ll u, ll l, ll r, ll x, ll y){
            if(!u){
                return {};
            }
            if(x <= l && r <= y) {
                return f[u].op;
            }
     
            ll m = (l + r) >> 1;
            Operation cur;
            if(x <= m) {
                cur = query(f[u].l, l, m, x, y);
            }
            if(y > m) {
                cur = cur + query(f[u].r, m + 1, r, x, y);
            }
            return cur;
        }
     
        Operation query(ll &root, ll l, ll r){
            return query(root, 1, len, l, r);
        }
    };

    //预处理根

    struct Operation{ 
        ll sum, cnt;

        Operation(ll p = 0){
            if(p){
                sum = p;
                cnt = 1;
            }
            else{
                sum = 0;
                cnt = 0;
            }
        }
    };
     
    Operation operator+(Operation a, Operation b){
        Operation c;
        if(!a.cnt) return b;
        c.sum = a.sum + b.sum;
        c.cnt = a.cnt + b.cnt;
        return c;
    }

    void solve(){
        int n, m;
        cin >> n >> m;

        ll a[n + 1], root[n + 1];
        for(int i = 1; i <= n; i++){
            cin >> a[i];
            root[i] = i;
        }

        SegTree<Operation> tr(N, n);
        DSU dsu(N);
        tr.pos = n;

        for(int i = 1; i <= n; i++){
            tr.update(root[i], a[i], {i});
        }

        for(int i = 1; i <= m; i++){
            int u, v;
            cin >> u >> v;

            if(dsu.set(u, v)) continue;

            u = dsu.find(u), v = dsu.find(v);
            if(dsu.get(u) >= dsu.get(v)){
                tr.merge(u, v, 1, n);
            }
            else{
                tr.merge(v, u, 1, n);
            }
            dsu.heuristic_merge(u, v);
        }

        int q;
        cin >> q;

        for(int i = 1; i <= q; i++){
            char op;
            cin >> op;

            int x, k;
            cin >> x >> k;

            if(op == 'Q'){
                int l = 1, r = n + 1;
                x = dsu.find(x);

                while(l < r){
                    int m = l + r >> 1;
                    if(tr.query(root[x], 1, m).cnt >= k) r = m;
                    else l = m + 1;
                }

                auto qwq = tr.query(root[x], 1, l);

                if(qwq.cnt < k || qwq.cnt > k){
                    cout << -1 << endl;
                }
                else{
                    cout << tr.query(root[x], l, l).sum << endl;
                }
            }
            else{
                if(dsu.set(x, k)) continue;
                x = dsu.find(x), k = dsu.find(k);

                if(dsu.get(x) >= dsu.get(k)){
                    tr.merge(root[x], root[k], 1, n);
                }
                else{
                    tr.merge(root[k], root[x], 1, n);
                }
                dsu.heuristic_merge(x, k);
            }
        }
    }

    signed main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cout.tie(0);

        int t = 1;
        // cin >> t;

        while (t--) {
            solve();
        }

        return 0;
    }

2024/8/5 11:33
加载中...