#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <map>
using namespace std;
// DSU structure to manage components (clouds)
struct DSU {
    vector<int> parent;
    vector<long long> sz;
    DSU(int n) {
        parent.resize(n + 1);
        iota(parent.begin(), parent.end(), 0);
        sz.assign(n + 1, 1);
    }
    int find(int i) {
        if (parent[i] == i)
            return i;
        return parent[i] = find(parent[i]);
    }
};
// Use two hash functions to minimize collisions
const long long M1 = 1e9 + 7, P1 = 313;
const long long M2 = 1e9 + 9, P2 = 331;
const int MAX_VAL = 1000001;
vector<long long> p1_powers(MAX_VAL);
vector<long long> p2_powers(MAX_VAL);
// Global state variables
DSU dsu(0);
vector<int> p;
vector<map<int, int>> diffs;
vector<pair<long long, long long>> component_hashes;
int bad_components_count = 0;
long long total_q4_pairs = 0;
map<pair<long long, long long>, long long> hash_to_total_size;
void precompute_powers() {
    p1_powers[0] = 1;
    p2_powers[0] = 1;
    for (int i = 1; i < MAX_VAL; ++i) {
        p1_powers[i] = (p1_powers[i - 1] * P1) % M1;
        p2_powers[i] = (p2_powers[i - 1] * P2) % M2;
    }
}
// Helper to manage modulo arithmetic for negative results
long long norm(long long val, long long mod) {
    return (val % mod + mod) % mod;
}
// Updates the total pair count when a group's total size changes
void change_pair_contribution(pair<long long, long long> hash, long long size_delta) {
    if (hash == make_pair(0LL, 0LL)) return;
    pair<long long, long long> comp_hash = {-hash.first, -hash.second};
    comp_hash.first = norm(comp_hash.first, M1);
    comp_hash.second = norm(comp_hash.second, M2);
    long long old_size_h = hash_to_total_size[hash];
    long long new_size_h = old_size_h + size_delta;
    if (hash != comp_hash) {
        long long size_ch = hash_to_total_size[comp_hash];
        total_q4_pairs += size_delta * size_ch;
    } else {
        total_q4_pairs -= old_size_h * (old_size_h - 1) / 2;
        total_q4_pairs += new_size_h * (new_size_h - 1) / 2;
    }
    hash_to_total_size[hash] = new_size_h;
}
// Incrementally updates a component's diff map and hash
void update_diff_and_hash(int root, int val, int count_delta) {
    int old_count = diffs[root][val];
    int new_count = old_count + count_delta;
    long long h1_delta = norm((long long)(new_count - old_count) * p1_powers[val], M1);
    long long h2_delta = norm((long long)(new_count - old_count) * p2_powers[val], M2);
    component_hashes[root].first = norm(component_hashes[root].first + h1_delta, M1);
    component_hashes[root].second = norm(component_hashes[root].second + h2_delta, M2);
    diffs[root][val] = new_count;
    if (new_count == 0) {
        diffs[root].erase(val);
    }
}
// Removes a component's contribution from global stats
void remove_from_stats(int root) {
    if (diffs[root].empty()) return;
    bad_components_count--;
    change_pair_contribution(component_hashes[root], -dsu.sz[root]);
}
// Adds a component's contribution to global stats
void add_to_stats(int root) {
    if (diffs[root].empty()) return;
    bad_components_count++;
    change_pair_contribution(component_hashes[root], dsu.sz[root]);
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    precompute_powers();
    int n, q;
    cin >> n >> q;
    p.resize(n + 1);
    vector<int> q_array(n + 1);
    dsu = DSU(n);
    diffs.resize(n + 1);
    component_hashes.resize(n + 1, {0, 0});
    for (int i = 1; i <= n; ++i) {
        cin >> p[i];
        q_array[i] = p[i];
    }
    sort(q_array.begin() + 1, q_array.end());
    // Initialize components and their hashes incrementally
    for (int i = 1; i <= n; ++i) {
        if (p[i] != q_array[i]) {
            update_diff_and_hash(i, p[i], 1);
            update_diff_and_hash(i, q_array[i], -1);
        }
    }
    
    // Initialize global counts
    for(int i=1; i<=n; ++i) {
        if(!diffs[i].empty()){
            bad_components_count++;
            hash_to_total_size[component_hashes[i]]++;
        }
    }
    
    map<pair<long long, long long>, bool> visited;
    for(auto const& [hash, size] : hash_to_total_size) {
        if(visited[hash]) continue;
        pair<long long, long long> comp_hash = {-hash.first, -hash.second};
        comp_hash.first = norm(comp_hash.first, M1);
        comp_hash.second = norm(comp_hash.second, M2);
        
        if (hash != comp_hash) {
             total_q4_pairs += size * hash_to_total_size[comp_hash];
        } else {
             total_q4_pairs += size * (size - 1) / 2;
        }
        visited[hash] = true;
        visited[comp_hash] = true;
    }
    for (int k = 0; k < q; ++k) {
        int type;
        cin >> type;
        if (type == 1) {
            int u, v;
            cin >> u >> v;
            int root_u = dsu.find(u);
            int root_v = dsu.find(v);
            
            if (p[u] == p[v]) continue;
            if (root_u != root_v) {
                remove_from_stats(root_u);
                remove_from_stats(root_v);
                
                update_diff_and_hash(root_u, p[u], -1);
                update_diff_and_hash(root_u, p[v], 1);
                update_diff_and_hash(root_v, p[v], -1);
                update_diff_and_hash(root_v, p[u], 1);
                
                add_to_stats(root_u);
                add_to_stats(root_v);
            }
            swap(p[u], p[v]);
        } else if (type == 2) {
            int u, v;
            cin >> u >> v;
            int root_u = dsu.find(u);
            int root_v = dsu.find(v);
            if (root_u != root_v) {
                if (dsu.sz[root_u] < dsu.sz[root_v]) swap(root_u, root_v);
                remove_from_stats(root_u);
                remove_from_stats(root_v);
                
                dsu.parent[root_v] = root_u;
                dsu.sz[root_u] += dsu.sz[root_v];
                
                for (auto const& [val, count] : diffs[root_v]) {
                    update_diff_and_hash(root_u, val, count);
                }
                
                add_to_stats(root_u);
            }
        } else if (type == 3) {
            cout << (bad_components_count == 0 ? "DA\n" : "NE\n");
        } else { // type 4
            cout << total_q4_pairs << "\n";
        }
    }
    return 0;
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |