Codeforces375D Tree and Queries
2020-11-24 03:01
1146 查看
题目链接
题目大意
给定一棵 \(n\) 个节点的树,根节点为 \(1\)。每个节点上有一个颜色 \(c_i\)
\(m\) 次询问。
每次询问给出 \(u\) \(k\):询问在以 \(u\) 为根的子树中,出现次数 \(≥k\) 的颜色有多少种。
解题思路
可以开棵权值线段树
如果当前颜色出现的次数 \(cnt[i] = x\), 就把树的第 \(x\) 个位置的值 \(+ 1\)
那么对于每个询问的 \(k\) 输出树的第 \(k\) 个位置的值即可
AC_Code
#include<bits/stdc++.h> #define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,n,a) for (int i=n;i>=a;i--) #define int long long #define pb push_back #define fi first #define se second using namespace std; const int N = 3e5 + 10; struct Tree{ int l , r , lazy , sum; }tree[N << 2]; void push_up(int rt) { tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum; } void push_down(int rt) { int x = tree[rt].lazy; tree[rt].lazy = 0; tree[rt << 1].lazy = tree[rt << 1 | 1].lazy = x; tree[rt << 1].sum += (tree[rt << 1].r - tree[rt << 1].l + 1) * x; tree[rt << 1 | 1].sum += (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1) * x; } void build(int l , int r , int rt) { tree[rt].l = l , tree[rt].r = r , tree[rt].lazy = 0; if(l == r) { tree[rt].sum = 0; return ; } int mid = l + r >> 1; build(l , mid , rt << 1); build(mid + 1 , r , rt << 1 | 1); push_up(rt); } void update_range(int L , int R , int rt , int val) { int l = tree[rt].l , r = tree[rt].r; if(L <= l && r <= R) { tree[rt].lazy += val; tree[rt].sum += (r - l + 1) * val; return ; } push_down(rt); int mid = l + r >> 1; if(L <= mid) update_range(L , R , rt << 1 , val); if(R > mid) update_range(L , R , rt << 1 | 1 , val); push_up(rt); } int query_range(int L , int R , int rt) { int l = tree[rt].l , r = tree[rt].r; if(L <= l && r <= R) return tree[rt].sum; push_down(rt); int mid = l + r >> 1 , ans = 0; if(L <= mid) ans += query_range(L , R , rt << 1); if(R > mid) ans += query_range(L , R , rt << 1 | 1); return ans; } struct Edge{ int nex , to; }edge[N << 1]; int head , TOT; void add_edge(int u , int v) { edge[++ TOT].nex = head[u] ; edge[TOT].to = v; head[u] = TOT; } int dep , sz , hson , HH; int col , n , m , up; int cnt , sum ; vector<pair<int , int>>Q , ans; void dfs(int u , int far) { dep[u] = dep[far] + 1; sz[u] = 1; for(int i = head[u] ; i ; i = edge[i].nex) { int v = edge[i].to; if(v == far) continue ; dfs(v , u); sz[u] += sz[v]; if(sz[v] > sz[hson[u]]) hson[u] = v; } } void calc(int u , int far, int val) { cnt[col[u]] += val; if(val == 1) { int k = cnt[col[u]]; update_range(k , k , 1 , 1); } if(val == -1) { int k = cnt[col[u]] + 1; update_range(k , k , 1 , -1); } for(int i = head[u] ; i ; i = edge[i].nex) { int v = edge[i].to; if(v == far || v == HH) continue ; calc(v , u , val); } } void dsu(int u , int far , int op) { for ad8 (int i = head[u] ; i ; i = edge[i].nex) { int v = edge[i].to; if(v == far || v == hson[u]) continue ; dsu(v , u , 0); } if(hson[u]) dsu(hson[u] , u , 1) , HH = hson[u]; calc(u , far , 1); for(auto i : Q[u]) { int id = i.fi , k = i.se; int res = query_range(k , k , 1); ans.pb(make_pair(id , res)); } HH = 0; if(!op) calc(u , far , -1); } signed main() { ios::sync_with_stdio(false); cin.tie(0) , cout.tie(0); cin >> n >> m; rep(i , 1 , n) cin >> col[i]; rep(i , 1 , n - 1) { int u , v; cin >> u >> v; add_edge(u , v) , add_edge(v , u); } rep(i , 1 , m) { int u , k; cin >> u >> k; Q[u].pb(make_pair(i , k)); } build(1 , 100000 , 1); dfs(1 , 0); dsu(1 , 0 , 0); sort(ans.begin() , ans.end()); for(auto i : ans) cout << i.se << '\n'; return 0; }
相关文章推荐
- 【编程鹿】害 学element-ui 看这篇就够了
- 当div设置contentEditable=true时,重置其内容后无法光标定位
- 使用layui实现左侧菜单栏及动态操作tab项的方法
- 使用layui框架实现点击左侧导航切换右侧内容且右侧选项卡跟随变化的效果
- Element-UI中Select选择器讲解(el-select详解)
- 鸿蒙HarmonyOS and 大疆Tello 无人机 BUILD SUCCESS
- OLAP引擎这么多,为什么苏宁选择用Druid?
- 我画着图,FluentAPI 她自己就生成了
- JS UI框架:构建用户界面布局说明
- 一文学会主流Ansible Web UI的部署与使用 | 万字长文
- 一种可以使Guest访问公网又可以被Host访问的网络配置方式
- @RequestParam,@RequestBody,@PathVariable注解还分不清吗?
- mysql +sqlalchemy query中的datetime转换str
- 聊聊用 UUID/GUID 作为主键那些坑
- TikTok为何繁荣,Quibi为何失败
- element ui table 表头错位问题解决
- Promethues:rocketmq_exporter初始化安装
- 安装Photoshop时出现The installation cannot continue as the installer file may be damaged. Download the in
- 19-爬虫解析利器pyquery详解
- JUC阻塞队列之BlockedQueue(七)