Count on a tree

题意:求路径 u到v上的 第k小的权重。

题解:先DFS建数, 然后对于每个节点往上跑出一颗主席树, 然后每次更新。 查询的时候, u, v, k, 找到  z = lca(u,v) , p = anc[z][0], 然后对于这条路上左边子节点的个数就可以被表示为u,v的树- z,p的树上的值。

然后主要是LCA不怎么用写搓了, 找了好久的bug。 汗。

代码:

 #include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const LL mod = (int)1e9+;
const int N = 1e5 + ;
const int M = 5e6 + ;
vector<int> son[N];
int lson[M], rson[M], cnt[M];
int anc[N][];
int tot, t;
int a[N], w[N], deep[N], root[N];
int id(int x){
return lower_bound(a+, a++t, x) - a;
}
int Build(int l, int r){
int now = ++tot;
cnt[now] = ;
if(l < r){
int m = l+r >> ;
lson[now] = Build(l, m);
rson[now] = Build(m+, r);
}
return now;
}
int Update(int l, int r, int pre, int c, int v){
int now = ++tot;
cnt[now] = cnt[pre] + v;
if(l < r){
int m = l+r >> ;
if(c <= m){
rson[now] = rson[pre];
lson[now] = Update(l, m, lson[pre], c, v);
}
else {
lson[now] = lson[pre];
rson[now] = Update(m+, r, rson[pre], c, v);
}
}
return now;
} void dfs(int o, int u){
deep[u] = deep[o] + ;
root[u] = Update(, t, root[o], id(w[u]), );
for(int i = ; i < son[u].size(); i++){
int v = son[u][i];
if(v == o) continue;
anc[v][] = u;
for(int j = ; j < ; j++) anc[v][j] = anc[anc[v][j-]][j-];
dfs(u, v);
}
}
int lca(int u, int v){
if(deep[u] < deep[v]) swap(u, v);
for(int i = ; i >= ; i--)
if(deep[anc[u][i]] >= deep[v]) u = anc[u][i];
if(u == v) return v;
for(int i = ; i >= ; i--)
if(anc[u][i] != anc[v][i])
u = anc[u][i], v = anc[v][i];
return anc[u][];
}
int Query(int l, int r, int c1, int c2, int d1, int d2, int k){
if(l == r) return a[l];
int m = l+r >> ;
int num = cnt[lson[c1]] + cnt[lson[c2]] - cnt[lson[d1]] - cnt[lson[d2]];
if(num >= k) return Query(l, m, lson[c1], lson[c2], lson[d1], lson[d2], k);
else return Query(m+, r, rson[c1], rson[c2], rson[d1], rson[d2], k-num);
}
int main(){
int n, q, u, v, k, p, z;
scanf("%d%d", &n, &q);
for(int i = ; i <= n; i++){
scanf("%d", &w[i]);
a[i] = w[i];
}
for(int i = ; i < n; i++){
scanf("%d%d", &u, &v);
son[u].pb(v);
son[v].pb(u);
}
sort(a+, a++n);
for(int i = ; i <= n; i++) a[++t] = a[i];
root[] = Build(, t);
dfs(, );
while(q--){
scanf("%d%d%d", &u, &v, &k);
z = lca(u, v);
p = anc[z][];
printf("%d\n", Query(, t, root[u], root[v], root[z], root[p], k));
}
return ;
}

Count on a tree

Count on a tree 树上区间第K小的更多相关文章

  1. Count on a tree(树上路径第K小)

    题目链接:https://www.spoj.com/problems/COT/en/ 题意:求树上A,B两点路径上第K小的数 思路:主席树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表上. ...

  2. SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)

    题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ...

  3. E - Count on a tree 树上第K小

    主席树的入门题目,这道题的题意其实就是说,给你一棵树,询问在两个节点之间的路径上的区间第K小 我们如何把树上问题转换为区间问题呢? 其实DFS就可以,我们按照DFS的顺序,对线段树进行建树,那么这个树 ...

  4. Count on a tree 树上主席树

    Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...

  5. 线段树维护区间前k小

    线段树维护区间前k小 $ solution: $ 觉得超级钢琴太麻烦?在这里线段树提供一条龙服务 . 咳咳,开始讲正题!这道题我们有一个和超级钢琴复杂度一样 $ ~O(~\sum x\times lo ...

  6. 主席树总结(经典区间第k小问题)(主席树,线段树)

    接着上一篇总结--可持久化线段树来整理吧.点击进入 这两种数据结构确实有异曲同工之妙.结构是很相似的,但维护的主要内容并不相同,主席树的离散化.前缀和等思想也要更难理解一些. 闲话 话说刚学习主席树的 ...

  7. A - 低阶入门膜法 - K-th Number (主席树查询区间第k小)

    题目链接:https://cn.vjudge.net/contest/284294#problem/A 题目大意:主席树查询区间第k小. 具体思路:主席树入门. AC代码: #include<i ...

  8. HDU 2665.Kth number 区间第K小

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. POJ 2014.K-th Number 区间第k小 (归并树)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 57543   Accepted: 19893 Ca ...

随机推荐

  1. UR机器人通信--上位机通信(python)

    一.通信socket socket()函数 Python 中,我们用 socket()函数来创建套接字,语法格式如下: socket.socket([family[, type[, proto]]]) ...

  2. 【JDK】JDK源码分析-CountDownLatch

    概述 CountDownLatch 是并发包中的一个工具类,它的典型应用场景为:一个线程等待几个线程执行,待这几个线程结束后,该线程再继续执行. 简单起见,可以把它理解为一个倒数的计数器:初始值为线程 ...

  3. ASP.NET Core Web API 跨域(CORS) Cookie问题

    身为一个Web API,处理来自跨域不同源的请求,是一件十分合理的事情. 先上已有的文章,快速复制粘贴,启用CORS: Microsoft:启用 ASP.NET Core 中的跨域请求 (CORS) ...

  4. 浏览器输入URL到返回页面的全过程

    [问题描述] 在浏览器输入www.baidu.com,然后,浏览器显示相应的百度页面,这个过程究竟发生了什么呢? [第一步,解析域名,找到主机] 正常情况下,浏览器会缓存DNS一段时间,一般2分钟到3 ...

  5. 史上最全面的SignalR系列教程-1、认识SignalR

    SignalR 是什么? SignalR 是一个面向 ASP.NET 开发人员的库,可简化将实时 web 功能添加到应用程序的过程. 实时 web 功能是让服务器代码将内容推送到连接的客户端立即可用, ...

  6. Tunnel Warfare HDU - 1540 (线段树不同子树的合并)

    在抗日战争期间,华北平原广大地区进行了大规模的隧道战. 一般来说,通过隧道连接的村庄排成一列. 除了两端,每个村庄都与两个相邻的村庄直接相连. 入侵者经常对一些村庄发动袭击并摧毁其中的部分隧道. 八路 ...

  7. 使用JMS接口接入WebSphere MQ消息

    在你的应用程序中利用IBM WebSphere MQ消息中间件提供Java消息服务开放接口. IBM WebSphere MQ(WMQ)是一套面向消息的中间件(message-oriented mid ...

  8. 【0812 | Day 13】闭包函数/装饰器/迭代器

    目录 闭包函数 无参装饰器 有参装饰器 迭代器 闭包函数 一.什么是闭包? 闭包指的是:函数内部函数对外部作用域而非全局作用域的引用. def outter(): x = 1 def inner(): ...

  9. Duilib的圆角矩形 抗锯齿优化 弥补RoundRect不足(网易云信borderround版本)

    VListBox class="list" name="list" padding="5,3,5,3" bordersize="1 ...

  10. JMeter的JTL大文件解析

    1.背景 不知大家在使用JMeter工具进行性能测试时,是否遇到过JTL结果文件过大导致GUI页面长时间解析无响应的问题.这种情况往往出现在稳定性测试场景下,此时的JTL文件大小可能已经达到G级别了. ...