【CF375D】Tree and Queries
阿新 • • 發佈:2021-06-15
題目
題目連結:https://codeforces.com/problemset/problem/375/D
給定一棵 \(n\) 個節點的有根樹,節點有顏色,\(m\) 次詢問一個點的子樹內出現次數 \(\geq k\) 的顏色數有多少。
\(n\leq 10^5\)。
思路
dsu on tree 板子題。
本來太板子不想寫的,但是因為太久沒寫了就水了一道題。
直接維護一個桶表示出現次數等於下標的顏色數量即可。
時間複雜度 \(O(n\log n+m)\)。
程式碼
#include <bits/stdc++.h> #define mp make_pair #define fi first #define se second using namespace std; const int N=100010; int n,m,tot,head[N],a[N],cnt[N],sum[N],ans[N],siz[N],son[N],id[N],rk[N]; vector<pair<int,int> > ask[N]; struct edge { int next,to; }e[N*2]; void add(int from,int to) { e[++tot]=(edge){head[from],to}; head[from]=tot; } void dfs1(int x,int fa) { siz[x]=1; for (int i=head[x];~i;i=e[i].next) { int v=e[i].to; if (v!=fa) { dfs1(v,x); siz[x]+=siz[v]; if (siz[v]>siz[son[x]]) son[x]=v; } } } void dfs2(int x,int fa,bool flag) { id[x]=++tot; rk[tot]=x; for (int i=head[x];~i;i=e[i].next) { int v=e[i].to; if (v!=fa && v!=son[x]) dfs2(v,x,1); } if (son[x]) dfs2(son[x],x,0); cnt[a[x]]++; sum[cnt[a[x]]]++; if (son[x]) for (int i=id[x]+1;i<id[son[x]];i++) cnt[a[rk[i]]]++,sum[cnt[a[rk[i]]]]++; for (int i=0;i<ask[x].size();i++) ans[ask[x][i].se]=sum[ask[x][i].fi]; if (flag) for (int i=id[x];i<id[x]+siz[x];i++) sum[cnt[a[rk[i]]]]--,cnt[a[rk[i]]]--; } int main() { memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1,x,y;i<n;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } for (int i=1,x,y;i<=m;i++) { scanf("%d%d",&x,&y); ask[x].push_back(mp(y,i)); } tot=0; dfs1(1,0); dfs2(1,0,1); for (int i=1;i<=m;i++) cout<<ans[i]<<"\n"; return 0; }