HYSBZ 1483 夢幻布丁

HYSBZ 1483 夢幻布丁

模擬鏈表,鏈表啓發式合併

題意

N個布丁擺成一行,進行M次操作.每次將某個顏色的布丁全部變成另一種顏色的,然後再詢問當前一共有多少段顏色.例如顏色分別爲1,2,2,1的四個布丁一共有3段顏色.

思路

暴力建出布丁的鏈表,記錄每種顏色的起始位置,結束位置。

合併時將一個顏色的鏈表遍歷,全改成另一種顏色,統計對ans的影響。並將鏈表連起來。

爲了防止退化,統計出每個顏色的size,進行啓發式合併。nc數組是記錄某顏色實際的位置用的。

所以對於這道題,我們先將初始的答案處理出來,考慮將一個顏色全部暴力修改爲另一種顏色之後對答案的影響,就是如果這個位置左面或者右面和目標顏色相同,ans- -。
但是由於我們要啓發式合併,有可能交換兩個顏色,這裏有個小問題需要處理,如果我們要將顏色1變爲顏色2,但是由於啓發式合併顏色2併到了顏色1上,以後找顏色2時我們應該找顏色1,怎麼辦呢…
處理辦法就是用一個nc[i]數組(nowcolor…)記錄i顏色當前是是什麼顏色,遇到要交換的情況時就swap(nc[a],nc[b]);

代碼

#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define M(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=2000007;
int c[MAXN], sz[MAXN], nc[MAXN];
int he[MAXN], ta[MAXN], ne[MAXN];
int ans;
void merge(int a, int b)
{
    if(sz[a]==0) return;
    for(int i=he[a];~i;i=ne[i])
    {
        if(c[i-1]==b) ans--;
        if(c[i+1]==b) ans--;
    }
    for(int i=he[a];~i;i=ne[i])
    {
        c[i]=b;
    }
    ne[ta[b]]=he[a];ta[b]=ta[a];
    sz[b]+=sz[a];sz[a]=0;
    he[a]=ta[a]=-1;
}
int main()
{
    int n, m;
    while(scanf("%d%d", &n, &m)==2)
    {
        M(he, -1), M(ta, -1), M(ne, -1);M(sz, 0);
        ans=0;
        for(int i=1;i<=n;i++)
        {
            int tmp;
            scanf("%d", &tmp);
            c[i]=tmp;
            if(ta[tmp]==-1) ta[tmp]=i;
            ne[i]=he[tmp];
            he[tmp]=i;
            if(c[i]!=c[i-1]) ans++;
            nc[tmp]=tmp;
            sz[tmp]++;
        }
        for(int i=1;i<=m;i++)
        {
            int op;scanf("%d", &op);
            if(op==1)
            {
                int c1, c2;scanf("%d%d", &c1, &c2);
                if(c1==c2) continue;
                else
                {
                    if(sz[nc[c1]]>sz[nc[c2]])
                        swap(nc[c1], nc[c2]);
                    merge(nc[c1], nc[c2]);
                }
            }
            else
            {
                printf("%d\n", ans);
            }
        }
    }
    //system("pause");
    return 0;
}
發佈了169 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章