bzoj 1483 链表 + 启发式合并

思路:将颜色相同的建成一个链表, 变颜色的时候进行链表的启发式合并。。

因为需要将小的接到大的上边,所以要用个f数组。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int, int>

using namespace std;

const int N = 1e6 + 7;
const int M = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 +7;

int n, m, ans, f[N], a[N];
struct node {
    node(int id, node *nx) {
        this->id = id;
        this->nx = nx;
    }
    int id;
    node *nx;
} *head[N];

void Insert(int x, int id) {
    node *p = new node(id, head[x]->nx);
    head[x]->nx = p;
    head[x]->id++;
}

void Merge(int x, int y) {
    if(x == y) return;

    if(head[f[x]]->id > head[f[y]]->id) swap(f[x], f[y]);
    x = f[x], y = f[y];

    node *cur =  head[x];

    while(cur -> nx != NULL) {
        cur = cur -> nx;
        int id = cur->id;
        if(a[id - 1] == y) ans--;
        if(a[id + 1] == y) ans--;
    }


    cur = head[x];
    while(cur -> nx != NULL) {
        cur = cur -> nx;
        int id = cur -> id;
        a[id] = y;
    }

    cur = head[y];
    while(cur -> nx != NULL) {
        cur = cur -> nx;
    }

    cur->nx = head[x]->nx;
    head[y]->id += head[x]->id;
    head[x]->id = 0;
    head[x]->nx = NULL;


}

int main() {

    for(int i = 1; i <= 1e6; i++) {
        f[i] = i;
        head[i] = new node(0, NULL);
    }

    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        if(a[i] != a[i - 1]) ans++;
        Insert(a[i], i);
    }


    while(m--) {
        int op; scanf("%d", &op);
        if(op == 1) {
            int x, y; scanf("%d%d", &x, &y);
            Merge(x, y);
        } else {
            printf("%d\n", ans);
        }
    }
    return 0;
}
/*
*/

 

posted @ 2018-07-09 09:34  NotNight  阅读(153)  评论(0编辑  收藏  举报