SPOJ COT Count on a tree(树上主席树 + LCA 求点第k小)题解
题意:n个点的树,每个点有权值,问你u~v路径第k小的点的权值是?
思路:
树上主席树就是每个点建一棵权值线段树,具体看JQ博客,LCA用倍增logn求出,具体原理看这里
树上主席树我每个点的存的是点u到源点1的权值线段树,那我求点u到v的所有点,显然是 u + v - lca - fa[lca],就是u到1 + v到1 - 多算的lca - 多算的fa[lca]。不能减去两个lca不然少一个点了,
LCA板子:
//LCA
int fa[maxn][];
int dep[maxn];
void lca_dfs(int u, int pre, int d){
dep[u] = d;
fa[u][] = pre;
for(int i = head[u]; i != -; i = edge[i].next)
if(edge[i].v != pre)
lca_dfs(edge[i].v, u, d + );
}
void lca_update(){
for (int i = ; ( << i) <= n; i++)
for(int u = ; u <= n; u++)
fa[u][i] = fa[fa[u][i - ]][i - ];
}
int lca_query(int u, int v){
if(dep[u] < dep[v]) swap(u, v);
int d = dep[u] - dep[v];
for(int i = ; ( << i) <= d; i++) {
if(d & ( << 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;
}
代码:
#include<cmath>
#include<set>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = + ;
const int M = maxn * ;
const ull seed = ;
const int INF = 0x3f3f3f3f;
const int MOD = ;
int n, m;
int root[maxn], a[maxn], tot;
struct Edge{
int v, next;
}edge[maxn << ];
int head[maxn], tol;
void addEdge(int u, int v){
edge[tol].v = v;
edge[tol].next = head[u];
head[u] = tol++;
}
struct node{
int lson, rson;
int sum;
}T[maxn * ];
void init(){
memset(T, , sizeof(T));
memset(root ,, sizeof(root));
memset(head, -, sizeof(head));
tot = tol = ;
}
vector<int> ve;
int getid(int x){
return lower_bound(ve.begin(), ve.end(), x) - ve.begin() + ;
}
void update(int l, int r, int &now, int pre, int v, int pos){
T[++tot] = T[pre], T[tot].sum += v, now = tot;
if(l == r) return;
int m = (l + r) >> ;
if(pos <= m)
update(l, m, T[now].lson, T[pre].lson, v, pos);
else
update(m + , r, T[now].rson, T[pre].rson, v, pos);
}
void build(int now, int pre){
update(, n, root[now], root[pre], , getid(a[now]));
for(int i = head[now]; i != -; i = edge[i].next){
int v = edge[i].v;
if(v == pre) continue;
build(v, now);
}
}
int query(int l, int r, int now, int pre, int lca, int flca, int k){
if(l == r) return l;
int m = (l + r) >> ;
int sum = T[T[now].lson].sum + T[T[pre].lson].sum - T[T[lca].lson].sum - T[T[flca].lson].sum;
if(sum >= k)
return query(l, m, T[now].lson, T[pre].lson, T[lca].lson, T[flca].lson, k);
else
return query(m + , r, T[now].rson, T[pre].rson, T[lca].rson, T[flca].rson, k - sum);
} //LCA
int fa[maxn][];
int dep[maxn];
void lca_dfs(int u, int pre, int d){
dep[u] = d;
fa[u][] = pre;
for(int i = head[u]; i != -; i = edge[i].next)
if(edge[i].v != pre)
lca_dfs(edge[i].v, u, d + );
}
void lca_update(){
for (int i = ; ( << i) <= n; i++)
for(int u = ; u <= n; u++)
fa[u][i] = fa[fa[u][i - ]][i - ];
}
int lca_query(int u, int v){
if(dep[u] < dep[v]) swap(u, v);
int d = dep[u] - dep[v];
for(int i = ; ( << i) <= d; i++) {
if(d & ( << 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;
}
int main(){
init();
ve.clear();
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)
scanf("%d", &a[i]), ve.push_back(a[i]);
sort(ve.begin(), ve.end());
ve.erase(unique(ve.begin(), ve.end()), ve.end());
for(int i = ; i <= n - ; i++){
int u, v;
scanf("%d%d", &u, &v);
addEdge(u, v);
addEdge(v, u);
}
lca_dfs(, , );
lca_update();
build(, );
while(m--){
int u, v, k;
scanf("%d%d%d", &u, &v, &k);
int lca = lca_query(u, v);
int ans = query(, n, root[u], root[v], root[lca], root[fa[lca][]], k);
printf("%d\n", ve[ans - ]);
}
return ;
}
SPOJ COT Count on a tree(树上主席树 + LCA 求点第k小)题解的更多相关文章
- BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 5217 Solved: 1233 ...
- Count on a tree 树上主席树
Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...
- spoj COT - Count on a tree (树上第K小 LCA+主席树)
链接: https://www.spoj.com/problems/COT/en/ 思路: 首先看到求两点之前的第k小很容易想到用主席树去写,但是主席树处理的是线性结构,而这道题要求的是树形结构,我们 ...
- bzoj 2588 Spoj 10628. Count on a tree(主席树)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- 【bzoj2588】Spoj 10628. Count on a tree 离散化+主席树
题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始为0,即第一个 ...
- bzoj 2588: Spoj 10628. Count on a tree【主席树+倍增】
算是板子,把值离散化,每个点到跟上做主席树,然后查询的时候主席树上用u+v-lca-fa[lca]的值二分 #include<iostream> #include<cstdio> ...
- [Bzoj2588]Count on a tree(主席树+LCA)
Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...
- 【BZOJ2588】Count On a Tree(主席树)
[BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...
- SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)
COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to ...
随机推荐
- Jmeter post请求传参问题
同线程组引用参数 举例1:新增数据bizId,然后将此次新增数据删除 添加新增数据接口,然后查询数据列表,正则表达式提取bizId 在删除接口引用此值${bizId} 添加断言,执行查看结果
- Elasticsearch学习笔记(五)索引元数据和集群元数据
一.索引元数据 执行:GET /ecommerce/product/1 返回结果: { "_index": "ecommerce", "_ty ...
- node js 爬虫爬取静态页面,
先打一个简单的通用框子 //根据爬取网页的协议 引入对应的协议, http||https var http = require('https'); //引入cheerio 简单点讲就是node中的jq ...
- tfs权限设置
需求,管理员用户可以看到tfs里面的所有项目,现在需要给某个开发人员设置权限,只让其看到其中某一个项目. 一.tfs服务器设置 1.在服务器管理器中的[本地用户和组]中添加一个新用户,并在“组”将新用 ...
- netcorec程序部署配置
IIS方式: 1:iis配置netcore发布的文件 2:iis设置运行库无托管模式 3:安装DotNetCore.1.0.4_1.1.1-WindowsHosting.exe 4:安装dotnet- ...
- weblogic使用wlst脚本实现自动部署
创建weblogic的server和cluster ip="10.20.0.2" nwport=8001 wwport=9001 nwlist=[ ('wtdsrwnw','Clu ...
- 基于FPGA的视频时序生成
之前用FPGA做过视频时序方面的设计,现将视频时序的设计方法分享给大家,希望对大家有所帮助. 时序部分可以参考CEA-861D,VESA时序标准. 1080P一帧视频中,一行有2200个像素,其中28 ...
- string函数详解(配案例)
多说无益上码~ #include<iostream> #include<algorithm> #include<cmath> #include<cstring ...
- JS中将json字符串转为json对象的三种方式
第一种:利用JSON的parse方法,即jsonObj=JSON.parse(jsonStr); 第二种:jsonObj = eval('(' + jsonStr+ ')'); 第三种:比较难理解:j ...
- react使用create-react-app创建的项目部署
一.在所有的项目代码编写完成后,react项目直接部署是无法正常访问的 1.问题一 网页无法正常的浏览器刷新,刷新会报404错,路由找不到页面 2.问题二 路由跳转后,浏览器后退按钮点击后,页面不刷新 ...