CodeForces - 375D Tree and Queries(树上启发式合并)
生活随笔
收集整理的這篇文章主要介紹了
CodeForces - 375D Tree and Queries(树上启发式合并)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目鏈接:點擊查看
題目大意:給出一棵有根樹,每個節點都有一個編號代表顏色,現在給出m個詢問,每個詢問的形式為u k,需要回答以u為根節點的子樹中,數量超過k的顏色有多少種
題目分析:樹上啟發式合并模板題,只不過一開始我不太會處理如何快速獲取超過k的顏色有多少種,傻傻的想了半天數據結構無果,想用map二分,結果發現只能對key二分,而不能對val二分,如果模擬的話又太麻煩,如果直接暴力的話時間復雜度又上來了,想了半天無果后去看了看別人的代碼,發現了一種真的很巧妙的方法,就是用另一個cntt數組,記錄cnt數組每個出現次數的次數,換句話說每次當cnt數組新紀錄顏色之后,用cntt數組記錄一下cnt數組,會造成的影響是,若一個顏色出現了n次,那么cnt[color]=n,同時cntt[1]=cntt[2]=....=cntt[n-1]=cntt[n]=1,這樣如果我們想直接查找出現k次的顏色,直接訪問cntt[k]就是我們想要的結果了,想一想是不是
剩下的就沒什么難度了,不過對于這個題目有個小坑,雖然題目說了給出的樹是以點 1 為根的有根樹,但題目給數據時給出的邊卻是以無向邊的形式給出的,所以我們需要按照無向邊的形式存邊,訪問的時候還是用v!=fa的形式訪問就好了
代碼:
#include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<map> #include<set> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int color[N],ans[N],son[N],num[N],cnt[N],cntt[N];//cnt記錄顏色數,cntt記錄cnt的個數 bool vis[N];vector<int>node[N];vector<pair<int,int>>Q[N];//<id,num>void dfs_son(int u,int fa) {num[u]=1;son[u]=-1;for(auto v:node[u]){if(v==fa)continue;dfs_son(v,u);num[u]+=num[v];if(son[u]==-1||num[v]>num[son[u]])son[u]=v;} }void cal(int u,int fa,int val) {if(val==-1)cntt[cnt[color[u]]]--;cnt[color[u]]+=val;if(val==1)cntt[cnt[color[u]]]++;for(auto v:node[u]){if(vis[v]||v==fa)continue;cal(v,u,val);} }void dfs(int u,int fa,int keep) {for(auto v:node[u]){if(v==son[u]||v==fa)continue;dfs(v,u,0);}if(son[u]!=-1){dfs(son[u],u,1);vis[son[u]]=true;}cal(u,fa,1);for(auto i:Q[u]){int id=i.first;int k=i.second;ans[id]=cntt[k];}if(son[u]!=-1)vis[son[u]]=false;if(!keep)cal(u,fa,-1); }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",color+i);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}for(int i=1;i<=m;i++){int u,k;scanf("%d%d",&u,&k);Q[u].push_back(make_pair(i,k));}dfs_son(1,-1);dfs(1,-1,1);for(int i=1;i<=m;i++)printf("%d\n",ans[i]);return 0; }?
總結
以上是生活随笔為你收集整理的CodeForces - 375D Tree and Queries(树上启发式合并)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1288E M
- 下一篇: CodeForces - 1200E C