啟發式合併

2022-06-27 03:09:10 字數 1273 閱讀 1869

推薦部落格 :

其實啟發式合併核心思想就是將小的集合合併到大的集合上面

例題 : hdu 4358

求一顆樹上以每個點為子樹中權值出現 k 次的個數有多少個

#include using namespace std;

#define ll long long

const int maxn = 1e5+5;

int n, k;

int a[maxn];

vectorve[maxn], vv;

int size[maxn], son[maxn];

int que[maxn];

void init()

void dfs1(int x)

}}int sum[maxn], ans[maxn];

int res = 0;

bool vis[maxn];

void edit(int x, int sp)

}void dfs(int x, int sp)

if (son[x]) dfs(son[x], 1), vis[son[x]] = 1;

edit(x, 1); //遍歷x的所有結點 新增重兒子以外的貢獻

ans[x] = res; //記錄答案

if (son[x]) vis[son[x]] = 0; //重兒子的標記取消

if (!sp) edit(x, -1); //貢獻取消

}int main()

sort(vv.begin(), vv.end());

vv.erase(unique(vv.begin(), vv.end()), vv.end());

for(int i = 1; i <= n; i++) a[i] = lower_bound(vv.begin(), vv.end(), a[i])-vv.begin()+1;

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

dfs1(1); dfs(1, 0);

int q;

cin >> q;

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

printf("case #%d:\n", kas++);

for(int i = 1; i <= n; i++) printf("%d\n", ans[que[i]]);

sign = 1;

//for(int i = 1; i <= n; i++) printf("%d ", sum[i]);

}return 0;

}

啟發式合併

啟發式合併 暴力合併 將兩個資料結構合併,只需要將小的資料結構中的元素乙個乙個的插入大的資料結構o n o n o n 如果題目只有插入操作沒有 總o n logn o nlogn o nlog n 因為每次合併,所有資料結構總大小為n,設兩個資料結構大小為a,b a b a,b a b a,b a...

啟發式合併

includeconst int n 5e5 5 int f n d n r n p n int find int i int unionn int i,int j int main 並查集 按秩啟發式合併 bzoj4668 冷戰 題目大意 給出n個軍工廠和m 個操作,操作分為兩類 0 u v,這次...

啟發式合併

啟發式合併本質上是一種優化的暴力,可用於擁有穩定結構的資料結構。考慮夢幻布丁 hnoi2009 顯然的暴力思路是用鍊錶維護每種顏色的位置,然後每次修改的時候暴力合併兩條鏈。不難證明,這樣的最壞時間複雜度將達到 o n 2 不能接受。可以觀察到,合併的時間複雜度只與被合併的鏈長度有關,所以可以想到優化...