日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【启发式合并】梦幻布丁(金牌导航 启发式合并-1/luogu 3201)

發(fā)布時間:2023/12/3 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【启发式合并】梦幻布丁(金牌导航 启发式合并-1/luogu 3201) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

夢幻布丁

金牌導(dǎo)航 啟發(fā)式合并-1

luogu 3201

題目大意

有若干個布丁,給出它們的顏色,每次將一個顏色的所有布丁變成另一種顏色,然后詢問有多少段連續(xù)的數(shù)

輸入樣例

4 3 1 2 2 1 2 1 2 1 2

輸出樣例

3 1

樣例解釋

初始時布丁顏色依次為 1,2,2,1,三段顏色分別為 [1,1], [2,3], [4,4]
一次操作后,布丁的顏色變?yōu)?,1,1,1,只有[1,4]一段顏色

數(shù)據(jù)范圍

1?n,m?105,1?ai,x,y?1061 \leqslant n, m \leqslant 10^5,1 \leqslant a_i ,x, y \leqslant 10^61?n,m?105,1?ai?,x,y?106

提示

請注意,不保證顏色的編號不大于 n,也不保證 x≠yx \neq yx?=y,m 不是顏色的編號上限

解題思路

如果每次暴力查詢時間O(nm)O(nm)O(nm),會TLETLETLE
對于每次合并,考慮把小的合并到大的中,這樣可以有效降低時間
對于集合AAA,如果和BBB合并(∣A∣?∣B∣)(|A|\leqslant|B|)(A?B),那么AAA所在集合大小變?yōu)?span id="ozvdkddzhkzd" class="katex--inline">∣A∣+∣B∣|A|+|B|A+B,變大了一倍,所以集合∣A∣|A|A最多合并lognlognlogn次,nnn個集合時間為O(nlogn)O(nlogn)O(nlogn)
對于更改顏色,可以用一個b數(shù)組存下第i種顏色存在第幾個顏色中,這樣可以O(shè)(1)實現(xiàn)交換兩個子集,就可以使小的合并到大的中

代碼

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define ll long long #define N 100010 using namespace std; int n, m, x, y, ans, s[N*10], b[N*10], st[N*10], nx[N], head[N*10], color[N]; void add(int x, int y)//加入點 {b[x] = x;//初始存在自己if (!head[x]) st[x] = y;//第一條邊nx[y] = head[x];head[x] = y;s[x]++; } void solve(int x, int y) {for (int i = head[x]; i; i = nx[i]){if (y == color[i - 1]) ans--;//相同就合并了,數(shù)量-1if (y == color[i + 1]) ans--;}for (int i = head[x]; i; i = nx[i])color[i] = y;//、、變色s[y] += s[x];//累加nx[st[y]] = head[x];//連在該子集后面st[y] = st[x];head[x] = s[x] = st[x] = 0; } int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i){scanf("%d", &color[i]);if (color[i] != color[i - 1]) ans++;add(color[i], i);}while(m--){scanf("%d", &x);if (x == 2) printf("%d\n", ans);else{scanf("%d%d", &x, &y);if (x == y) continue;if (s[b[x]] > s[b[y]]) swap(b[x], b[y]);//小的合并到大的if (!s[b[x]]) continue;solve(b[x], b[y]);}}return 0; }

總結(jié)

以上是生活随笔為你收集整理的【启发式合并】梦幻布丁(金牌导航 启发式合并-1/luogu 3201)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。