CodeForces 375D Tree and Queries 莫队||DFS序

Tree and Queries

题意:有一颗以1号节点为根的树,每一个节点有一个自己的颜色,求出节点v的子数上颜色出现次数>=k的颜色种类。

题解:使用莫队处理这个问题,将树转变成DFS序区间,然后就是开一个数据记录下出现次数为k次的颜色数目,查询的时候直接返回这个数组中的对应的值就行了。

注意的就是记得将节点的颜色传递给dfs序对应位置的颜色。 这个忘记了找了好久的bug。

代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
 4 #define LL long long
 5 #define ULL unsigned LL
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define lson l,m,rt<<1
10 #define rson m+1,r,rt<<1|1
11 #define max3(a,b,c) max(a,max(b,c))
12 #define min3(a,b,c) min(a,min(b,c))
13 #define _S(X) cout << x << ' ';
14 #define __S(x) cout << x << endl;
15 typedef pair<int,int> pll;
16 const int INF = 0x3f3f3f3f;
17 const LL mod =  (int)1e9+7;
18 const int N = 2e5 + 100;
19 int in[N], out[N], col[N], cc[N], cnt[N], num[N], ans[N];
20 vector<int> son[N];
21 int tot, n, m, blo;
22 struct Node{
23     int l, r, id, k;
24 }q[N];
25 bool cmp(Node x1, Node x2){
26     if(x1.l/blo != x2.l/blo) return x1.l/blo < x2.l/blo;
27     return x1.r < x2.r;
28 }
29 void Add(int c){
30     num[++cnt[c]]++;
31 }
32 void Remove(int c){
33     num[cnt[c]--]--;
34 }
35 void dfs(int o, int u){
36     in[u] = ++tot;
37     cc[tot] = col[u];
38     for(int i = 0; i < son[u].size(); i++){
39         if(son[u][i] == o) continue;
40         dfs(u, son[u][i]);
41     }
42     out[u] = tot;
43 }
44 int main(){
45     scanf("%d%d", &n, &m);
46     for(int i = 1; i <= n; i++)
47         scanf("%d", &col[i]);
48     blo = sqrt(n);
49     int u, v;
50     for(int i = 1; i < n; i++){
51         scanf("%d%d", &u, &v);
52         son[u].pb(v);
53         son[v].pb(u);
54     }
55     dfs(-1,1);
56     for(int i = 1; i <= m; i++){
57         q[i].id = i;
58         scanf("%d%d", &u, &v);
59         q[i].k = v;
60         q[i].l = in[u];
61         q[i].r = out[u];
62     }
63     sort(q+1, q+1+m, cmp);
64    // cout << "vujgfuy" << endl;
65     int l = 1, r = 0;
66     for(int i = 1; i <= m; i++)
67     {
68         while(r < q[i].r) Add(cc[++r]);
69         while(r > q[i].r) Remove(cc[r--]);
70         while(l < q[i].l) Remove(cc[l++]);
71         while(l > q[i].l) Add(cc[--l]);
72         ans[q[i].id] = num[q[i].k];
73     }
74     for(int i = 1; i <= m; i++)
75         printf("%d\n", ans[i]);
76     return 0;
77 }
CF375 D

 

posted @ 2018-06-03 17:07  Schenker  阅读(111)  评论(0编辑  收藏  举报