Cod sursa(job #2054859)

Utilizator mlc_oficialBoris Barca mlc_oficial Data 2 noiembrie 2017 17:00:17
Problema Paduri de multimi disjuncte Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 6.19 kb
#include <cassert>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <memory>
 
using namespace std;
 
constexpr int64_t inf = 1e18;

class Reader {
public:
    Reader(istream& _in) : in(_in), idx(kBuffSize - 1), buff(new char[kBuffSize]) { Advance(); }
    
    Reader& operator>>(char& ch) {
        ch = Current();
        Advance();
        return *this;
    }
    
    Reader& operator>>(char str[]) {
        while (isspace(Current())) {
            Advance();
        }
        
        int n = 0;
        while (not isspace(Current())) {
            str[n++] = Current();
            Advance();
        }
        str[n] = 0;
        return *this;
    }
    
    Reader& operator>>(string& str) {
        while (isspace(Current())) {
            Advance();
        }
        
        while (not isspace(Current())) {
            str.push_back(Current());
            Advance();
        }
        return *this;
    }
    
    Reader& operator>>(int32_t& value) {
        bool sign = false;
        while (not isdigit(Current())) {
            sign |= Current() == '-';
            Advance();
        }
        
        value = 0;
        while (isdigit(Current())) {
            value = (value << 1) + (value << 3) + (Current() - '0');
            Advance();
        }
        value ^= (value ^ -value) & -sign;
        return *this;
    }
    
    Reader& operator>>(int64_t& value) {
        bool sign = false;
        while (not isdigit(Current())) {
            sign |= Current() == '-';
            Advance();
        }
        
        value = 0;
        while (isdigit(Current())) {
            value = (value << 1) + (value << 3) + (Current() - '0');
            Advance();
        }
        value ^= (value ^ -value) & -sign;
        return *this;
    }
    
    Reader& operator>>(double& value) {
        bool sign = false;
        while (not isdigit(Current())) {
            sign |= Current() == '-';
            Advance();
        }
        
        value = .0;
        while (isdigit(Current())) {
            value = value * 10.0 + (Current() - '0');
            Advance();
        }
        if (Current() == '.') {
            Advance();
            
            double multiplier = 0.1;
            while (isdigit(Current())) {
                value += (Current() - '0') * multiplier;
                multiplier *= 0.1;
                Advance();
            }
        }
        
        if (sign) {
            value = -value;
        }
        return *this;
    }
private:
    static constexpr int kBuffSize = 1 << 12;
    
    char Current() const {
        return buff[idx];
    }
    
    void Advance() {
        if (++idx == kBuffSize) {
            in.read(buff.get(), kBuffSize);
            idx = 0;
        }
    }
    
    istream& in;
    int idx;
    unique_ptr<char[]> buff;
};

class Printer {
public:
    Printer(ostream& _out) : out(_out), idx(0), buff(new char[kBuffSize]), digits(new char[kMaxNumDigits]) { }
    ~Printer() { Flush(); out.flush(); }

    Printer& operator<<(int32_t value) {
        if (value < 0) {
            PutChar('-');
            value = -value;
        }
        int num_digits = 0;
        do {
            const uint32_t aux = ((uint64_t)3435973837 * value) >> 35;
            digits[num_digits++] = value - (aux << 1) - (aux << 3) + '0';
            value = aux;
        } while (value > 0);
        
        while (num_digits--) {
            PutChar(digits[num_digits]);
        }
        return *this;
    }
    
    Printer& operator<<(int64_t value) {
        if (value < 0) {
            PutChar('-');
            value = -value;
        }
        int num_digits = 0;
        do {
            const uint64_t aux = value / 10;
            digits[num_digits++] = value - (aux << 1) - (aux << 3) + '0';
            value = aux;
        } while (value > 0);
        
        while (num_digits--) {
            PutChar(digits[num_digits]);
        }
        return *this;
    }
    
    Printer& operator<<(const char *str) {
        for (int i = 0; str[i]; i += 1) {
            PutChar(str[i]);
        }
        return *this;
    }
    
    Printer& operator<<(const string& str) {
        for (auto&& ch : str) {
            PutChar(ch);
        }
        return *this;
    }
    
    Printer& operator<<(const char& ch) {
        PutChar(ch);
        return *this;
    }
    
    Printer& operator <<(double value) {
        if (value < 0) {
            PutChar('-');
            value = -value;
        }
        
        const int64_t integer_part = static_cast<int64_t>(value);
        *this << integer_part << '.' << static_cast<int64_t>((value - integer_part) * kPrecision + 0.5);
        return *this;
    }
private:
    static constexpr int kBuffSize = 1 << 12;
    static constexpr int kMaxNumDigits = 20;
    static constexpr double kPrecision = 1e9;
    
    void Flush() {
        out.write(buff.get(), idx);    
    }
    
    void PutChar(const char& ch) {
        buff[idx++] = ch;
        if (idx == kBuffSize) {
            Flush();
            idx = 0;
        }
    }
    
    ostream& out;
    int idx;
    unique_ptr<char[]> buff, digits;    
};

class DisjointSets {
public:
    DisjointSets(const int n) : x(n, -1) { }
    
    bool Unite(int a, int b) {
        a = FindRoot(a);
        b = FindRoot(b);
        if (a != b) {
            if (x[b] < x[a]) {
                x[b] += x[a];
                x[a] = b;
            } else {
                x[a] += x[b];
                x[b] = a;
            }
            return true;
        }
        return false;
    }
    
    int FindRoot(int node) {
        return x[node] < 0 ? node : x[node] = FindRoot(x[node]);    
    }
private:
    vector<int> x;
};

enum QueryType {
    UNITE = 1,
    QUERY = 2
};

int main() {
    #ifdef INFOARENA
    ifstream cin("disjoint.in");
    ofstream cout("disjoint.out");
    #endif
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    
    Reader r(cin); Printer p(cout);
    
    int n, q; r >> n >> q;
    DisjointSets DS(n);
    while (q--> 0) {
        int type, a, b; r >> type >> a >> b; a -= 1; b -= 1;
        if (type == QueryType::UNITE) {
            DS.Unite(a, b);
        } else {
            p << (DS.FindRoot(a) == DS.FindRoot(b) ? "DA" : "NU") << '\n';
        }
    }
    return 0;
}