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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【CF375D】Trees and Queries——树上启发式合并

發布時間:2025/4/16 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【CF375D】Trees and Queries——树上启发式合并 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(題面不是來自Luogu)

題目描述

有一個大小為n且以1為根的樹,樹上每個點都有對應的顏色ci。現給出m次詢問v, k,問以v為根的子樹中有多少種顏色至少出現了k次。

輸入格式

第一行兩個數n,m表示樹的大小以及詢問的次數。

第二行n個數表示樹上每個結點的顏色。

接下來的n-1行,每行兩個數a, b表示樹上的邊。

接下來m行,每行兩個數v, k表示詢問。

輸出格式

m行,每行一個數表示第i次詢問的答案。

樣例輸入1

8 5 1 2 2 3 3 2 3 3 1 2 1 5 2 3 2 4 5 6 5 7 5 8 1 2 1 3 1 4 2 3 5 3

樣例輸出1

2 2 1 0 1

?

樣例輸入2

4 1 1 2 3 4 1 2 2 3 3 4 1 1

樣例輸出2

4

數據范圍

2≤n≤100000

1≤m≤100000

1≤ci≤100000

1≤a, b≤n, a≠b

1≤v≤n, 1≤k≤100000

對于其中30%的數據保證n,m≤100且ci≤n

對于其中60%的數據保證n≤5000

?

  (7:20)今天為了打這個題的正解學了dsu on tree。需要學習的同學請看我的上一篇博客。

  樹上啟發式合并主要解決的就是這類靜態子樹統計問題。

  對于這題,我們維護兩個數組cnt和upr,分別表示某種顏色出現的數量和出現次數大于某個次數的顏色的種類數。每次暴力累計子樹信息時,出現一個顏色先++cnt[color[i]],然后++upr[color[i]]。容易想到,這樣可以保證不重不漏地統計到所有達到upr[i]的顏色,并且不會重復累加。剩下的套dsu on tree板子即可。

代碼:

  • #include?<cstdio>??
  • #include?<iostream>??
  • #include?<cctype>??
  • #include?<cstring>??
  • #include?<vector>??
  • #define?maxn?100010??
  • using?namespace?std;??
  • template?<class?T>??
  • void?read(T?&x)?{??
  • ????x?=?0;??
  • ????char?ch?=?getchar();??
  • ????while?(!isdigit(ch))??
  • ????????ch?=?getchar();??
  • ????while?(isdigit(ch))?{??
  • ????????x?=?x?*?10?+?(ch?^?48);??
  • ????????ch?=?getchar();??
  • ????}??
  • }??
  • int?n,?m,?color[maxn],?upr[maxn],?cnt[maxn],?ans[maxn];??
  • struct?Query?{??
  • ????int?k,?id;??
  • };??
  • vector<Query>?Q[maxn];??
  • int?head[maxn],?top;??
  • struct?E?{??
  • ????int?to,?nxt;??
  • }?edge[maxn?<<?1];??
  • inline?void?insert(int?u,?int?v)?{??
  • ????edge[++top]?=?(E)?{v,?head[u]};??
  • ????head[u]?=?top;??
  • }??
  • int?size[maxn],?son[maxn];??
  • void?dfs(int?u,?int?pre)?{??
  • ????size[u]?=?1;??
  • ????for?(int?i?=?head[u];?i;?i?=?edge[i].nxt)?{??
  • ????????int?v?=?edge[i].to;??
  • ????????if?(v?==?pre)?continue;??
  • ????????dfs(v,?u);??
  • ????????size[u]?+=?size[v];??
  • ????????if?(size[son[u]]?<?size[v])??
  • ????????????son[u]?=?v;??
  • ????}??
  • }??
  • int?CurSon;??
  • void?cal(int?u,?int?pre,?int?val)?{??
  • ????if?(val?==?-1)???
  • ????????--upr[cnt[color[u]]];??
  • ????cnt[color[u]]?+=?val;??
  • ????if?(val?==?1)??
  • ????????++upr[cnt[color[u]]];??
  • ????for?(int?i?=?head[u];?i;?i?=?edge[i].nxt)?{??
  • ????????int?v?=?edge[i].to;??
  • ????????if?(v?==?CurSon?||?v?==?pre)?continue;??
  • ????????cal(v,?u,?val);??
  • ????}??
  • }??
  • void?dsu(int?u,?int?pre,?bool?op)?{??
  • ????for?(int?i?=?head[u];?i;?i?=?edge[i].nxt)?{??
  • ????????int?v?=?edge[i].to;??
  • ????????if?(v?==?pre?||?v?==?son[u])?continue;??
  • ????????dsu(v,?u,?0);??
  • ????}??
  • ????if?(son[u])??
  • ????????dsu(son[u],?u,?1),?CurSon?=?son[u];??
  • ????cal(u,?pre,?1);?CurSon?=?0;??
  • ????for?(int?i?=?0;?i?<?Q[u].size();?++i)???
  • ????????ans[Q[u][i].id]?=?upr[Q[u][i].k];??
  • ????if?(!op)??
  • ????????cal(u,?pre,?-1);??
  • }??
  • int?main()?{??
  • //??freopen("count.in",?"r",?stdin);??
  • //??freopen("count.out",?"w",?stdout);??
  • ????read(n),?read(m);??
  • ????for?(int?i?=?1;?i?<=?n;?++i)???
  • ????????read(color[i]);??
  • ????int?u,?v;??
  • ????for?(int?i?=?1;?i?<?n;?++i)?{??
  • ????????read(u),?read(v);??
  • ????????insert(u,?v),?insert(v,?u);??
  • ????}??
  • ????int?k;??
  • ????for?(int?i?=?1;?i?<=?m;?++i)?{??
  • ????????read(v),?read(k);??
  • ????????Q[v].push_back((Query)?{k,?i});??
  • ????}??
  • ????dfs(1,?0);??
  • ????dsu(1,?0,?1);??
  • ????for?(int?i?=?1;?i?<=?m;?++i)??
  • ????????printf("%d\n",?ans[i]);??
  • ????return?0;??
  • }??
  • 轉載于:https://www.cnblogs.com/TY02/p/11219304.html

    總結

    以上是生活随笔為你收集整理的【CF375D】Trees and Queries——树上启发式合并的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。