CF375D Tree and Queries
阿新 • • 發佈:2020-11-28
題意簡述
給一個\(n\)個節點的樹,根節點為\(1\),第\(i\)個節點有一個顏色\(c_i\),有\(m\)個詢問,每個詢問:
給\(u,k\),求以\(u\)為根的子樹出現次數\(\ge k\)的顏色個數。
\(n,m,k,c_i \le 10^5\)
簡單口胡
好像正解是\(n\log{n}\)的?我不會。
我整的是\(n\sqrt{n}\)的。
不難想到將樹轉成\(\text{dfn}\)序,然後以\(u\)為子樹的\(\text{dfn}\)序即為\([\text{dfn}_u,\text{dfn}_u + \text{siz}_u - 1]\),其中\(\text{siz}_u\)
然後莫隊既珂。
# include <bits/stdc++.h> using namespace std; const int N = 1e5 + 2; int n,m; int c[N]; // int l[1010],r[1010]; int dfn[N],dfn2[N],siz[N]; int son[N]; int Q[N],QQ[N]; int ans[N]; int C[N]; int len,num,dfntot = 0; struct node { int l,r,k,soc; }q[N]; vector <int> g[N]; int belong(int x) { return (x - 1) / len + 1; } bool compare(const struct node &a,const struct node &b) { return belong(a.l) ^ belong(b.l) ? (belong(a.l) < belong(b.l)) : (belong(a.l) & 1) ? a.r < b.r : a.r > b.r; } void dfs(int x,int fa) { // printf("%d\n",x); dfn[x] = ++dfntot; siz[x] = 1; C[dfn[x]] = c[x]; for(int i = 0; i < g[x].size(); i++) { int v = g[x][i]; if(v != fa) { dfs(v,x); siz[x] += siz[v]; if(siz[v] > siz[son[x]]) son[x] = v; } } dfn2[x] = dfntot; return; } // void dfs2(int x,int fa) // { // dfn[x] = ++dfntot; // if(son[x]) dfs2(son[x],x); // for(auto v : g[x]) // { // if(v != fa && v != son[x]) dfs2(v,x); // } // } void Del(int x) { // QQ[Q[c[x]]]--; --QQ[Q[C[x]]--]; } void Add(int x) { ++QQ[++Q[C[x]]]; // QQ[--Q[c[x]]]++; } int main(void) { scanf("%d%d",&n,&m); len = sqrt(n),num = (n - 1) / len + 1; for(int i = 1; i <= n; i++) { scanf("%d",&c[i]); } for(int i = 1; i < n; i++) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } dfs(1,0); // dfs2(1,0); for(int i = 1; i <= m; i++) { int u; scanf("%d%d",&u,&q[i].k); q[i].l = dfn[u],q[i].r = dfn2[u]; q[i].soc = i; } sort(q + 1, q + m + 1,compare); int L = 1,R = 0; for(int i = 1; i <= m; i++) { while(L < q[i].l) { Del(L++); } while(R > q[i].r) { Del(R--); } while(L > q[i].l) { Add(--L); } while(R < q[i].r) { Add(++R); } ans[q[i].soc] = QQ[q[i].k]; } for(int i = 1; i <= m; i++) printf("%d\n",ans[i]); return 0; }