cf375D. Tree and Queries(莫队)
生活随笔
收集整理的這篇文章主要介紹了
cf375D. Tree and Queries(莫队)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意
題目鏈接
給出一棵 n 個結點的樹,每個結點有一個顏色 c i 。 詢問 q 次,每次詢問以 v 結點為根的子樹中,出現次數 ≥k 的顏色有多少種。樹的根節點是1。
Sol
想到了主席樹和啟發式合并。。很顯然都不能做。
標算是dfs序上暴力莫隊。。甘拜下風
具體實現的時候可以直接用\(tim[i]\)表示第\(i\)個顏色的出現次數,\(ans[i]\)表示出現次數多于\(i\)的顏色的種類
由于左右端點移動的時候只會對一個\(ans[i]\)產生影響,所以修改是\(O(1)\)的
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 10; inline int read() {char c = getchar(); int x = 0, f = 1;while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();return x * f; } int N, M, dfn[MAXN], rev[MAXN], tot, block, bel[MAXN], siz[MAXN], col[MAXN], tims[MAXN], Ans[MAXN], out[MAXN]; vector<int> v[MAXN]; struct Query{int id, l, r, k;bool operator < (const Query &rhs) const {return bel[l] == bel[rhs.l] ? r < rhs.r : bel[l] < bel[rhs.l];} }Q[MAXN]; void dfs(int x, int fa) {dfn[x] = ++tot; rev[tot] = x; siz[x] = 1;for(int i = 0, to; i < v[x].size(); i++) {if((to = v[x][i]) == fa) continue;dfs(to, x); siz[x] += siz[to];} } void add(int x, int opt) {if(opt == 1) Ans[++tims[x]]++;else Ans[tims[x]--]--; } void solve() { sort(Q + 1, Q + M + 1);int l = 1, r = 0;for(int i = 1; i <= M; i++) {while(r > Q[i].r) add(col[rev[r--]], -1);while(r < Q[i].r) add(col[rev[++r]], 1);while(l < Q[i].l) add(col[rev[l++]], -1);while(l > Q[i].l) add(col[rev[--l]], 1);out[Q[i].id] = Ans[Q[i].k];///printf("%d\n", out[Q[i].id]);}for(int i = 1; i <= M; i++) printf("%d\n", out[i]);} int main() {N = read(); M = read(); block = sqrt(N);for(int i = 1; i <= N; i++) col[i] = read(), bel[i] = (i - 1) / block + 1;for(int i = 1; i <= N - 1; i++) {int x = read(), y = read();v[x].push_back(y); v[y].push_back(x);} dfs(1, 0);for(int i = 1; i <= M; i++) {Q[i].id = i; int x = read(); Q[i].k = read();Q[i].l = dfn[x];Q[i].r = dfn[x] + siz[x] -1;}solve();return 0; } /* */總結
以上是生活随笔為你收集整理的cf375D. Tree and Queries(莫队)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZABBIX监控JAVA日志文件
- 下一篇: 【Python爬虫学习笔记12】Ajax