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\n",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;

}

 

你可能感兴趣的:(ZOJ)