• [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;
    }
  • 相关阅读:
    闭包函数 (字符编码,文件处理,函数基础总结)
    函数参数详解
    文件处理及函数基础
    文件处理高级
    面向对象----反射
    正则表达式与re模块
    常用模块
    模块和包
    内置函数与匿名函数
    HDU
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8551823.html
Copyright © 2020-2023  润新知