Cod sursa(job #2657783)

Utilizator freak93Adrian Budau freak93 Data 11 octombrie 2020 23:10:19
Problema Paduri de multimi disjuncte Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.51 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

class SplayTree {
  public:
    struct Node {
        Node *parent = nullptr;
        Node *son[2] = {nullptr, nullptr};

        int flip = 0;

        int side() const {
            if (parent->son[0] == this)
                return 0;
            return 1;
        }

        bool root() const {
            return parent == nullptr || (this != parent->son[0] && this != parent->son[1]);
        }
    };
 
    static Node* push(Node *x) {
        if (!x || !x->flip)
            return x;
        swap(x->son[0], x->son[1]);
        for (int i = 0; i < 2; ++i)
            if (x->son[i])
                x->son[i]->flip^= 1;
        x->flip = 0;
        return x;
    }

    static void splay(Node *x) {
        while (!x->root()) {
            Node *p = x->parent;
            Node *g = p->parent;
            if (p->root())
                g = nullptr;
            push(g);
            push(p);
            push(x);
            if (!g) {
                rotate(p, x->side());
            }
            else {
                int sx = x->side();
                int sp = p->side();
                if (sx == sp) {
                    rotate(g, sp);
                    rotate(p, sx);
                } else {
                    rotate(p, sx);
                    rotate(g, sp);
                }
            }
        }
    }

    static void rotate(Node *p, int side) {
        Node *g = p->parent;
        Node *x = p->son[side];
        Node *y = x->son[side ^ 1];

        p->son[side] = y;
        x->son[side ^ 1] = p;

        if (!p->root()) {
            g->son[p->side()] = x;
        }
        if (y)
            y->parent = p;
        p->parent = x;
        x->parent = g;
    }

    static Node* first(Node *x) {
        while (push(x)->son[0])
            x = x->son[0];
        splay(x);
        return x;
    }
};

class LinkCutTree {
  public:
    LinkCutTree(int size): m_node(size) {}

    bool connected(int x, int y) {
        Node *xx = SplayTree::first(access(&m_node[x]));
        Node *yy = SplayTree::first(access(&m_node[y]));
        return xx == yy;
    }

    void link(int x, int y) {
        Node *xx = access(&m_node[x]);
        Node *yy = make_root(&m_node[y]);
        yy->parent = xx;
    }

    void delink(int x, int y) {
        Node *xx = make_root(&m_node[x]);
        Node *yy = access(&m_node[y]);
        access(xx);
        yy->parent = nullptr;
    }

  private:
    using Node = SplayTree::Node;

    void cut(Node *x) {
        SplayTree::push(x);
        Node *y = x->son[1];
        if (!y)
            return;
        x->son[1] = nullptr;
    }

    Node* access(Node *x) {
        SplayTree::splay(x);
        cut(x);
        while (x->parent) {
            Node *up = x->parent;
            SplayTree::splay(up);
            cut(up);

            up->son[1] = x;
            SplayTree::splay(x);
        }
        return x;
    }

    Node* make_root(Node *x) {
        access(x);
        x->flip ^= 1;
        cut(x);
        return x;
    }

    vector<SplayTree::Node> m_node;
};

int main() {
    ios::sync_with_stdio(false);
    ifstream cin("disjoint.in");
    ofstream cout("disjoint.out");

    int N, M; cin >> N >> M;
    LinkCutTree T(N);
    for (int i = 0; i < M; ++i) {
        int op; int x, y;
        cin >> op >> x >> y;
        --x; --y;
        if (op == 2) {
            if (T.connected(x, y))
                cout << "DA\n";
            else 
                cout << "NU\n";
        } else {
            T.link(x, y);
        }
    }
}