[HNOI 2009]梦幻布丁

Description

题库链接

维护一个序列 (A) 。支持以下操作:

  1. (X~Y) 将序列中所有的 (X) 变成 (Y)
  2. 询问序列颜色段数。

(1leq n,mleq 100000,0<A_i,X,Yleq 1000000)

Solution

这题做法挺多的,我写的是线段树大力合并。

均摊复杂度为 (O(nlog_2^2 n))

Code

//It is made by Awson on 2018.3.12
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('
'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 100000, C = 1000000;
void read(int &x) {
    char ch; bool flag = 0;
    for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
    for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
    x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); }

int n, m, flag[C+5], x, ans, opt, a, b;
struct Segment_tree {
    int root[C+5], ch[N*20+5][2], kl[N*20+5], kr[N*20+5], cnt[N*20+5], key[N*20+5], pos;
    queue<int>mem;
    void recycle(int o) {ch[o][0] = ch[o][1] = kl[o] = kr[o] = cnt[o] = key[o] = 0; mem.push(o); }
    void pushup(int o) {
    kl[o] = kl[ch[o][0]], kr[o] = kr[ch[o][1]], cnt[o] = cnt[ch[o][0]]+cnt[ch[o][1]];
    key[o] = key[ch[o][0]]+key[ch[o][1]]-(kr[ch[o][0]] == 1 && kl[ch[o][1]] == 1);
    }
    void insert(int &o, int l, int r, int loc) {
    if (!o) {if (!mem.empty()) o = mem.front(), mem.pop(); else o = ++pos; }
    if (l == r) {kl[o] = kr[o] = cnt[o] = key[o] = 1; return; }
    int mid = (l+r)>>1;
    if (loc <= mid) insert(ch[o][0], l, mid, loc);
    else insert(ch[o][1], mid+1, r, loc);
    pushup(o);
    }
    int merge(int a, int b) {
    if (!a || !b) return a+b;
    if (cnt[a] < cnt[b]) Swap(a, b);
    ch[a][0] = merge(ch[a][0], ch[b][0]);
    ch[a][1] = merge(ch[a][1], ch[b][1]);
    pushup(a); recycle(b); return a;
    }
}T;

void work() {
    read(n), read(m);
    for (int i = 1; i <= n; i++) {
    read(x), ans -= T.key[T.root[x]]; flag[x] = 1;
    T.insert(T.root[x], 1, n, i); ans += T.key[T.root[x]];
    }
    while (m--) {
    read(opt);
    if (opt == 2) writeln(ans);
    else {
        read(a), read(b); if (a == b) continue;
        ans -= T.key[T.root[a]]+T.key[T.root[b]], flag[a] = 0, flag[b] = 1;
        ans += T.key[T.root[b] = T.merge(T.root[a], T.root[b])]; T.root[a] = 0;
    }
    }
}
int main() {
    work(); return 0;
}
原文地址:https://www.cnblogs.com/NaVi-Awson/p/8551823.html