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

原文地址:https://www.cnblogs.com/MingSD/p/9129756.html

时间: 2024-08-08 22:00:13

CodeForces 375D Tree and Queries 莫队||DFS序的相关文章

codeforces 375D . Tree and Queries 启发式合并 || dfs序+莫队

题目链接 一个n个节点的树, 每一个节点有一个颜色, 1是根节点. m个询问, 每个询问给出u, k. 输出u的子树中出现次数大于等于k的颜色的数量. 启发式合并, 先将输入读进来, 然后dfs完一个节点就处理跟它有关的询问. 感觉不是很难, 然而.....WA了n次最后还是看的别人的代码 1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5

Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)

题目链接  Tree and Queries 题目大意  给出一棵树和每个节点的颜色.每次询问vj, kj 你需要回答在以vj为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少为kj. (莫队居然可以过) 首先转DFS序,这样就变成了区间查询. 然后直接套用莫队,求出每次询问状态下的t[],t[k]表示当前区间内拥有k个节点的颜色数量. 然后统计t[k] + t[k + 1], ..., t[MAX]即可,这个过程用树状数组维护. #include <bits/stdc++.h>

[Codeforces375D]Tree and Queries(莫队算法)

题意:给定一棵树,每个节点有颜色,对于每个询问(u,k)询问以u为根节点的子树下有多少种颜色出现次数>=k 因为是子树,跟dfs序有关,转化为一段区间,可以用莫队算法求解 直接用一个数组统计出现次数>=k的颜色 Code #include <cstdio> #include <algorithm> #include <cmath> #define N 100010 using namespace std; int n,m,A[N],bl[N],Ans[N],

CodeForces 375D. Tree and Queries【树上启发式合并】

传送门 题意 给出一棵 \(n\) 个结点的树,每个结点有一个颜色 \(c_i\) . 询问 \(q\) 次,每次询问以 \(v\) 结点为根的子树中,出现次数 \(\ge k\) 的颜色有多少种.树的根节点是 \(1\). 题解 反正我看见这个 \(\ge k\) 就觉得要用线段树,实际上好像不用写线段树的 Orz. 还是树上启发式合并,记录每种颜色出现的次数,然后线段树记录某种次数有多少颜色,更改就在线段树上改. 这是最后一道树上启发式合并的例题了,以后遇到再刷. #include <bit

CF 375D. Tree and Queries【莫队】

题意: 一棵树,询问一个子树内出现次数≥k≥k的颜色有几种 强制在线见上一道 用莫队不知道比分块高到哪里去了,超好写不用调7倍速度!!! 可以用分块维护出现次数这个权值,实现$O(1)-O(\sqrt{N})$修改查询 #pragma GCC optimize ("O2") #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #incl

SPOJ.COT2 Count on a tree II(树上莫队)

题目链接(同上一题苹果树) 为什么第10个点T了一晚上.. 下面那个却AC了?跑的也不慢. TLE: /* 在DFS序做莫队 当一个点不是另一个点的LCA时,需要加上它们LCA的贡献 */ #include <cmath> #include <cstdio> #include <cctype> #include <algorithm> #define gc() getchar() //#define gc() (SS==TT&&(TT=(SS

Gym101138D Strange Queries 莫队、前缀和、容斥

传送门 THUWC2019D1T1撞题可还行 以前有些人做过还问过我,但是我没有珍惜,直到进入考场才追悔莫及-- 设\(que_{i,j}\)表示询问\((1,i,1,j)\)的答案,那么询问\((a,b,c,d)=que_{b,d} - que_{a-1 , d} - que_{b , c - 1} + que_{a - 1 , c - 1}\) 把一个询问拆成\(4\)个询问,然后对这\(4\)个询问莫队就可以了 不知道怎么回事THUWC上想到了莫队想到了前缀和想到了容斥就是没想到莫队+前缀

SP10707 COT2 - Count on a tree II (树上莫队)

参考博客 对于树上的路径询问问题 O(1)的时间加入或删除一个点的贡献 -> \(O(n\sqrt n)\)的复杂度求出所有询问的答案 对树上的结点进行分块,离线询问后排序,顺序遍历暴力转移路径(转移时加入或删除路径上的点的贡献即可). 关于转移路径:首先定义路径:设\(T_u\)为\(u\) 到根的路径上边的集合,那么\(u\)到\(v\) 的路径上的边的集合就是\(T_u \triangle T_v\) (\(\triangle\) 是对称差).要从\(u\rightarrow v\) 转移

HDU5293(SummerTrainingDay13-B Tree DP + 树状数组 + dfs序)

Tree chain problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1798    Accepted Submission(s): 585 Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,-,n.The