• bzoj 1483 链表启发式合并


      首先我们可以比较容易的在n的时间内算出来开始的答案,我们维护一些链表,分别表示不同的颜色,那么我们在计算答案的时候,只需要扫一遍所有的链表,判断链表相邻两项是否在序列中相邻,不相邻的话肯定在这其中的一个唯一有一个断的点,也就是分成了两个不同的颜色段,直接累加答案就好了。

      然后我们对于每个询问,将颜色x换成颜色y,那么我们找到这两种颜色的链表,将小的链表连接到大的链表之后,同时统计由于合并两个链表而对答案造成的影响。这样直接合并是不行的,因为我们由于链表的长度而改变了合并的顺序,所以我们可以记录一个father[x],代表这个点的颜色,这样我们就可以合并了。

      

    /**************************************************************
        Problem: 1483
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:468 ms
        Memory:16820 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #define maxn 100010
    #define maxx 1000010
     
    using namespace std;
     
    int n,m;
    int c[maxn];
    int other[maxx],last[maxx],father[maxx],size[maxx];
    int ans;
     
    void swap(int &x,int &y)
    {
        int z=x;
        x=y; y=z;
    }
     
    void init()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&c[i]),size[c[i]]++;
        for (int i=1;i<=n;i++) other[i]=last[c[i]],last[c[i]]=i;
        ans=0;
        for (int i=1;i<=n;i++) if (c[i]!=c[i-1]) ans++;
        for (int i=1;i<=1000000;i++) father[i]=i;
    }
     
    void solve()
    {
        int k,x,y;
        while (m--)
        {
            scanf("%d",&k);
            if (k==2) printf("%d
    ",ans); else
            {
                scanf("%d%d",&x,&y);
                if (x==y) continue;
                if (father[x]>father[y]) swap(father[x],father[y]);
                x=father[x]; y=father[y];
                if (!size[x]) continue;
                for (int p=last[x];p;p=other[p])
                {
                    if (c[p]!=c[p-1]) ans--;
                    if ((p!=n)&&(c[p]!=c[p+1])) ans--;
                }
                for (int p=last[x];p;p=other[p]) c[p]=y;
                int head;
                for (int p=last[x];p;p=other[p])
                {
                    if (c[p]!=c[p-1]) ans++;
                    if ((p!=n)&&(c[p]!=c[p+1])) ans++;
                    head=p;
                }
                size[y]+=size[x]; size[x]=0;
                other[head]=last[y]; last[y]=last[x]; last[x]=0;
            }
        }
    }
     
     
    int main()
    {
        init();
        solve();
        return 0;
    }
  • 相关阅读:
    mybatisplus学习
    JSON数组读取和保存
    XML文件读写示例
    JSON代码示例
    Delphi接口示例代码
    获得wav语音文件时长
    javaweb注册页面学习之路(三)
    javaweb注册页面学习之路(二)
    javaweb注册页面学习之路(一)
    Django 目录
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3625730.html
Copyright © 2020-2023  润新知