Count on a tree SPOJ - COT (主席树,LCA)
You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer weight.
We will ask you to perform the following operation:
- u v k : ask for the kth minimum weight on the path from node u to node v
Input
In the first line there are two integers N and M. (N, M <= 100000)
In the second line there are N integers. The ith integer denotes the weight of the ith node.
In the next N-1 lines, each line contains two integers u v, which describes an edge (u, v).
In the next M lines, each line contains three integers u v k, which means an operation asking for the kth minimum weight on the path from node u to node v.
Output
For each operation, print its result.
Example
- Input:
- 8 5
- 105 2 9 3 8 5 7 7
- 1 2
- 1 3
- 1 4
- 3 5
- 3 6
- 3 7
- 4 8
2 5 1
2 5 2
2 5 3
2 5 4
7 8 2
- Output:
- 2
8
9
105
7
给出一棵树,每个点都自己的权重,然后给出树上的边,要求从节点 u 到节点 v 路径上的第 k 小的权重的大小。
因为权重可能很大,所以需要离散化。
主席树求区间第 k 小维护的是权值线段树的前缀和,然后通过区间相减得到查询区间的权值线段树
所以树形结构的第 k 小维护的也是权值线段树的前缀和,这里的前缀和表示从第 i 个结点到根的前缀和,比如样例的树是
那么我们用主席树把这八个结点维护成这个样子
那么要得到其中两个点(u,v)之间的树形结构,就可以看成 TREE(u) + TREE(v) - TREE(lca(u,v))- TREE(fa(lca(u,v))),把查询看成四棵树之间的相加相减,然后在求一下lca(u,v)就可以了,这里我比较懒直接用在线的写了
- /*
- .
- ';;;;;.
- '!;;;;;;!;`
- '!;|&#@|;;;;!:
- `;;!&####@|;;;;!:
- .;;;!&@$$%|!;;;;;;!'.`:::::'.
- '!;;;;;;;;!$@###&|;;|%!;!$|;;;;|&&;.
- :!;;;;!$@&%|;;;;;;;;;|!::!!:::;!$%;!$%` '!%&#########@$!:.
- ;!;;!!;;;;;|$$&@##$;;;::'''''::;;;;|&|%@$|;;;;;;;;;;;;;;;;!$;
- ;|;;;;;;;;;;;;;;;;;;!%@#####&!:::;!;;;;;;;;;;!&####@%!;;;;$%`
- `!!;;;;;;;;;;!|%%|!!;::;;|@##%|$|;;;;;;;;;;;;!|%$#####%;;;%&;
- :@###&!:;;!!||%%%%%|!;;;;;||;;;;||!$&&@@%;;;;;;;|$$##$;;;%@|
- ;|::;;;;;;;;;;;;|&&$|;;!$@&$!;;;;!;;;;;;;;;;;;;;;;!%|;;;%@%.
- `!!;;;;;;;!!!!;;;;;$@@@&&&&&@$!;!%|;;;;!||!;;;;;!|%%%!;;%@|.
- %&&$!;;;;;!;;;;;;;;;;;|$&&&&&&&&&@@%!%%;!||!;;;;;;;;;;;;;$##!
- !%;;;;;;!%!:;;;;;;;;;;!$&&&&&&&&&&@##&%|||;;;!!||!;;;;;;;$&:
- ':|@###%;:;;;;;;;;;;;;!%$&&&&&&@@$!;;;;;;;!!!;;;;;%&!;;|&%.
- !@|;;;;;;;;;;;;;;;;;;|%|$&&$%&&|;;;;;;;;;;;;!;;;;;!&@@&'
- .:%#&!;;;;;;;;;;;;;;!%|$$%%&@%;;;;;;;;;;;;;;;;;;;!&@:
- .%$;;;;;;;;;;;;;;;;;;|$$$$@&|;;;;;;;;;;;;;;;;;;;;%@%.
- !&!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;|@#;
- `%$!;;;;;;;;;;;$@|;;;;;;;;;;;;;;;;;;;;;;;;!%$@#@|.
- .|@%!;;;;;;;;;!$&%||;;;;;;;;;;;;;;;;;!%$$$$$@#|.
- ;&$!;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%#####|.
- |##$|!;;;;;;::'':;;;;;;;;;;;;;!%$$$@#@;
- ;@&|;;;;;;;::'''''':;;;;;;;|$&@###@|`
- .%##@|;;;;:::''''''''''::;!%&##$'
- `$##@$$@@&|!!;;;:'''''::::;;;;;|&#%.
- ;&@##&$%!;;;;;;::''''''''::;!|%$@#@&@@:
- .%@&$$|;;;;;;;;;;:'''':''''::;;;%@#@@#%.
- :@##@###@$$$$$|;;:'''':;;!!;;;;;;!$#@@#$;`
- `%@$$|;;;;;;;;:'''''''::;;;;|%$$|!!&###&'
- |##&%!;;;;;::''''''''''''::;;;;;;;!$@&:`!'
- :;!@$|;;;;;;;::''''''''''':;;;;;;;;!%&@$: !@#$'
- |##@@&%;;;;;::''''''''':;;;;;;;!%&@#@$%: '%%!%&;
- |&%!;;;;;;;%$!:''''''':|%!;;;;;;;;|&@%||` '%$|!%&;
- |@%!;;!!;;;||;:'''''':;%$!;;;;!%%%&#&%$&: .|%;:!&%`
- !@&%;;;;;;;||;;;:''::;;%$!;;;;;;;|&@%;!$; `%&%!!$&:
- '$$|;!!!!;;||;;;;;;;;;;%%;;;;;;;|@@|!$##; !$!;:!$&:
- |#&|;;;;;;!||;;;;;;;;!%|;;;;!$##$;;;;|%' `%$|%%;|&$'
- |&%!;;;;;;|%;;;;;;;;$$;;;;;;|&&|!|%&&; .:%&$!;;;:!$@!
- `%#&%!!;;;;||;;;;;!$&|;;;!%%%@&!;;;!!;;;|%!;;%@$!%@!
- !&!;;;;;;;;;||;;%&!;;;;;;;;;%@&!;;!&$;;;|&%;;;%@%`
- '%|;;;;;;;;!!|$|%&%;;;;;;;;;;|&#&|!!||!!|%$@@|'
- .!%%&%'`|$; :|$#%|@#&;%#%.
- */
- #include <map>
- #include <set>
- #include <list>
- #include <ctime>
- #include <cmath>
- #include <stack>
- #include <queue>
- #include <string>
- #include <vector>
- #include <cstdio>
- #include <bitset>
- #include <cstdlib>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #define lowbit(x) x & (-x)
- #define mes(a, b) memset(a, b, sizeof a)
- #define fi first
- #define se second
- #define pii pair<int, int>
- #define INOPEN freopen("in.txt", "r", stdin)
- #define OUTOPEN freopen("out.txt", "w", stdout)
- typedef unsigned long long int ull;
- typedef long long int ll;
- const int maxn = 1e5 + ;
- const int maxm = 1e5 + ;
- const int mod = 1e9 + ;
- const ll INF = 1e18 + ;
- const int inf = 0x3f3f3f3f;
- const double pi = acos(-1.0);
- const double eps = 1e-;
- using namespace std;
- int n, m;
- int cas, tol, T;
- struct Node {
- int l, r;
- int sum;
- } node[maxn * ];
- int a[maxn];
- int rt[maxn];
- bool vis[maxn];
- int deep[maxn];
- int fa[maxn][];
- vector<int> vec[maxn];
- vector<int> vv;
- void init() {
- tol = ;
- mes(a, );
- mes(rt, );
- mes(fa, );
- mes(vis, );
- mes(node, );
- mes(deep, );
- vv.clear();
- for(int i=; i<=n; i++)
- vec[i].clear();
- }
- int getid(int x) {
- return lower_bound(vv.begin(), vv.end(), x) - vv.begin() + ;
- }
- void lca_dfs(int u, int f, int d) {
- deep[u] = d;
- int len = vec[u].size();
- for(int i=; i<len; i++) {
- int v = vec[u][i];
- if(v == f) continue;
- if(fa[v][])continue;
- fa[v][] = u;
- lca_dfs(v, u, d+);
- }
- }
- void lca_update() {
- for(int j=; (<<j)<=n; j++) {
- for(int i=; i<=n; i++) {
- fa[i][j] = fa[fa[i][j-]][j-];
- }
- }
- }
- int lca_query(int u, int v) {
- if(deep[u] < deep[v]) swap(u, v);
- int f = deep[u] - deep[v];
- for(int i=; (<<i)<=f; i++) {
- if(f & (<<i)) {
- u = fa[u][i];
- }
- }
- if(u != v) {
- for(int i=(int)log2(n); i>=; i--) {
- if(fa[u][i] != fa[v][i]) {
- u = fa[u][i];
- v = fa[v][i];
- }
- }
- u = fa[u][];
- }
- return u;
- }
- void hjt_update(int l, int r, int &x, int y, int pos) {
- tol++;
- node[tol] = node[y];
- node[tol].sum++;
- x = tol;
- if(l == r) return ;
- int mid = (l + r) >> ;
- if(pos <= mid)
- hjt_update(l, mid, node[x].l, node[y].l, pos);
- else
- hjt_update(mid+, r, node[x].r, node[y].r, pos);
- }
- void hjt_build(int u, int f) {
- // printf("%d %d\n", u, f);
- hjt_update(, n, rt[u], rt[f], getid(a[u]));
- vis[u] = true;
- int len = vec[u].size();
- for(int i=; i<len; i++) {
- int v = vec[u][i];
- if(vis[v]) continue;
- if(v == f) continue;
- hjt_build(v, u);
- }
- }
- int hjt_query(int l, int r, int x, int y, int lca, int flca, int k) {
- if(l == r)
- return l;
- int mid = (l + r) >> ;
- int sum = node[node[x].l].sum + node[node[y].l].sum - node[node[lca].l].sum - node[node[flca].l].sum;
- if(k <= sum)
- return hjt_query(l, mid, node[x].l, node[y].l, node[lca].l, node[flca].l, k);
- else
- return hjt_query(mid+, r, node[x].r, node[y].r, node[lca].r, node[flca].r, k-sum);
- }
- int main() {
- scanf("%d%d", &n, &m);
- init();
- for(int i=; i<=n; i++) {
- scanf("%d", &a[i]);
- vv.push_back(a[i]);
- }
- sort(vv.begin(), vv.end());
- vv.erase(unique(vv.begin(), vv.end()), vv.end());
- for(int i=; i<n; i++) {
- int u, v;
- scanf("%d%d", &u, &v);
- vec[u].push_back(v);
- vec[v].push_back(u);
- }
- fa[][] = ;
- lca_dfs(, , );
- lca_update();
- hjt_build(, );
- while(m--) {
- int u, v, k;
- scanf("%d%d%d", &u, &v, &k);
- int ans = hjt_query(, n, rt[u], rt[v], rt[lca_query(u, v)], rt[fa[lca_query(u, v)][]], k);
- printf("%d\n", vv[ans-]);
- }
- return ;
- }
Count on a tree SPOJ - COT (主席树,LCA)的更多相关文章
- Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式)
Count on a tree SPOJ 10628 主席树+LCA(树链剖分实现)(两种存图方式) 题外话,这是我第40篇随笔,纪念一下.<( ̄︶ ̄)↗[GO!] 题意 是说有棵树,每个节点上 ...
- SPOJ COT Count on a tree(树上主席树 + LCA 求点第k小)题解
题意:n个点的树,每个点有权值,问你u~v路径第k小的点的权值是? 思路: 树上主席树就是每个点建一棵权值线段树,具体看JQ博客,LCA用倍增logn求出,具体原理看这里 树上主席树我每个点的存的是点 ...
- 【BZOJ2588】Count on a tree 题解(主席树+LCA)
前言:其实就是主席树板子啦……只不过变成了树上的查询 -------------------------- 题目链接 题目大意:求树上$u$到$v$路径第$k$大数. 查询静态区间第$k$大肯定是用主 ...
- ☆ [洛谷P2633] Count on a tree 「树上主席树」
题目类型:主席树+\(LCA\) 传送门:>Here< 题意:给出一棵树.每个节点有点权.问某一条路径上排名第\(K\)小的点权是多少 解题思路 类似区间第\(K\)小,但放在了树上. 考 ...
- BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树
2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...
- BZOJ2588 Count on a tree 【树上主席树】
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MB Submit: 7577 Solved: 185 ...
- 【洛谷2633】Count on a tree(树上主席树)
点此看题面 大致题意: 给你一棵树,每次问你两点之间第\(k\)小的点权,强制在线. 主席树 这种题目强制在线一般就是数据结构了. 而看到区间第\(k\)小,很容易就能想到主席树. 至少不会有人想到树 ...
- 🔺Count on a tree SPOJ - COT (无能为力。。。)
https://cn.vjudge.net/problem/SPOJ-COT 插上 大佬的代码 和 我的...以后再看吧... Count on a tree 大佬:http://www.cnblog ...
- BZOJ - 2588 Spoj 10628. Count on a tree (可持久化线段树+LCA/树链剖分)
题目链接 第一种方法,dfs序上建可持久化线段树,然后询问的时候把两点之间的所有树链扒出来做差. #include<bits/stdc++.h> using namespace std; ...
随机推荐
- 更新下载库update绝对详解
下载更新apk,基本上每个app都需要的功能,来看看吧,肯定有你想要的,以前都是自己写,近期想借助第三方的一个库来做,功能齐全,感觉不错,记录使用过程,虽然官方也有使用教程,不过毕竟粗略,网上也能搜到 ...
- 模拟ES6中的Promise实现,让原理一目了然
简介 Promise 对象用于延迟(deferred) 计算和异步(asynchronous )计算.一个Promise对象代表着一个还未完成,但预期将来会完成的操作.Promise 对象是一个返回值 ...
- 在java中写出完美的单例模式
1. 前言 单例(Singleton)应该是开发者们最熟悉的设计模式了,并且好像也是最容易实现的——基本上每个开发者都能够随手写出——但是,真的是这样吗? 作为一个Java开发者,也许你觉得自己对单例 ...
- 用 Weave Scope 监控集群 - 每天5分钟玩转 Docker 容器技术(175)
创建 Kubernetes 集群并部署容器化应用只是第一步.一旦集群运行起来,我们需要确保一起正常,所有必要组件就位并各司其职,有足够的资源满足应用的需求.Kubernetes 是一个复杂系统,运维团 ...
- 【原】Java学习笔记018 - 面向对象
package cn.temptation; public class Sample01 { public static void main(String[] args) { // 继承关系的子类可以 ...
- 树莓派3b+ Ubuntu 16.04 MATA系统 ssh远程登陆后修改主机名、用户密码和用户名
写在前面: 刚刚开始写博客,记录下自己的学习过程,备忘. 最近在使用树莓派做智能小车的开发,使用的是树莓派3b+,安装的是Ubuntu 16.04 MATA 系统,安装系统后需要修改主机名,登陆密码以 ...
- Eclipse编程中免除alt+斜杠,设置自动提示
用eclipse进行编程时,设置自动提示 .abcdefghijklmnopqrstuvwxyz@
- perf + Flame Graph火焰图分析程序性能
1.perf命令简要介绍 性能调优时,我们通常需要分析查找到程序百分比高的热点代码片段,这便需要使用 perf record 记录单个函数级别的统计信息,并使用 perf report 来显示统计结果 ...
- nginx 499状态码
Web服务器在用着nginx,在日志中偶尔会看到有499这个错误. rfc2616中,400-500间的错误码仅定义到了417,所以499应该是nginx自己定义的.后来想到读读nginx代码,疑问立 ...
- ###20175311MyCP(课下作业,必做)
MyCP(课下作业,必做) 作业题目 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP支持两个参数: java MyCP -tx XXX1.txt XXX2.b ...