HNOI2009 夢幻布丁

2022-07-26 12:48:14 字數 762 閱讀 9890

題目鏈結

把每一種數字想象成乙個佇列。如果暴力合併,時間複雜度必然很高,考慮啟發式合併:每次把數字少的佇列合併到數字多的佇列上去。每次合併,若數字少的佇列數字個數為 \(s\),則合併之後產生新佇列的大小必定不小於 \(2*s\)。時間複雜度 \(o(n \log_n)\)。

這樣合併產生了乙個問題:即原來要求將 \(a\) 全部變為 \(b\),現在將 \(b\) 全部變為了 \(a\)。需要標記一下每種數字本來是多少,若合併時出現問題,將 \(a\)、\(b\) 的標記值互換。

#include #include #include #include using namespace std;

const int n = 2333333;

int n, m, ans = 0, opt, x, y, a[n], f[n], sz[n], st[n], head[n], nxt[n];

void solve(int x, int y)

for(int i = head[x]; i; i = nxt[i]) a[i] = y;

nxt[st[x]] = head[y], head[y] = head[x], sz[y] += sz[x];

head[x] = st[x] = sz[x] = 0;}

int main()

for(int i = 1; i <= m; i++)

else printf("%d\n", ans);

}return 0;

}

HNOI2009 夢幻布丁

題意 n個布丁擺成一行,進行m次操作.每次將某個顏色的布丁全部變成另一種顏色的,然後再詢問當前一共有多少段顏色.例如顏色分別為1,2,2,1的四個布丁一共有3段顏色.對每個顏色的位置維護鍊錶。合併兩個顏色,連線鍊錶,統計貢獻。統計貢獻的複雜度是與鍊錶長度有關的。如果遍歷長度短的鍊錶那麼複雜度自然更小...

HNOI2009 夢幻布丁

n個布丁擺成一行,進行m次操作.每次將某個顏色的布丁全部變成另一種顏色的,然後再詢問當前一共有多少段顏色.例如顏色分別為1,2,2,1的四個布丁一共有3段顏色.輸入格式 第一行給出n,m表示布丁的個數和好友的操作次數.第二行n個數a1,a2.an表示第i個布丁的顏色從第三行起有m行,對於每個操作,若...

HNOI2009 夢幻布丁 線段樹合併

一開始是在splay專題下找的這道題,但是一想,好像更貼近線段樹的區間連續問題,然後就想著先去用線段樹去寫這道題,聽聞會出現顏色會超出1e7的範疇,所以,我就不考慮用陣列去開了,直接寫了map 的來解決這個問題。利用線段樹合併,對於已有的每個顏色來看,我們可以去知道最開始的情況,可以直接求得,然後就...