Description

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

Input

第一行两个整数N,M。
第二行有N个整数,其中第i个整数表示点i的权值。
后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
最后M行每行两个整数(u,v,k),表示一组询问。

Output

M行,表示每个询问的答案。最后一个询问不输出换行符

Sample 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
0 5 2
10 5 3
11 5 4
110 8 2

Sample Output

2
8
9
105
7

HINT

N,M<=100000
暴力自重。。。
 
题意 : 给你一棵树,每次询问任意两点间第 K 小的元素,强调在线。
思路分析 :还是利用主席树,在树上建立主席树,从根节点到当前节点建立线段树,借助 lca, 然后比如要查询 u, v 这段区间,要先找到u, v 之间的公共祖先 lca
代码示例 :
#define ll long long
const int maxn = 1e5+5;
const int mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f; int n, m;
int pre[maxn], rank[maxn];
vector<int>ve[maxn];
int dep[maxn];
int grand[maxn][22];
int root[maxn];
int cnt, ss;
struct node
{
int l, r;
int sum;
}t[maxn*20]; void update(int num, int &rt, int l, int r){
t[cnt++] = t[rt];
rt = cnt-1;
t[rt].sum++; if (l == r) return;
int m = (l+r)>>1;
if (num <= m) update(num, t[rt].l, l, m);
else update(num, t[rt].r, m+1, r);
} void dfs(int x, int fa){
for(int i = 1; i <= 20; i++){
grand[x][i] = grand[grand[x][i-1]][i-1];
}
int num = lower_bound(rank+1, rank+ss, pre[x])-rank;
root[x] = root[fa];
update(num, root[x], 1, n);
for(int i = 0; i < ve[x].size(); i++){
int to = ve[x][i];
if (to == fa) continue; dep[to] = dep[x]+1;
grand[to][0] = x;
dfs(to, x);
}
} void init(){
cnt = 1;
root[0] = 0;
t[0].l = t[0].r = t[0].sum = 0;
} int getlca(int u, int v){
if (dep[u] < dep[v]) swap(u, v); // u 是在下面的 for(int i = 20; i >= 0; i--){
if (dep[grand[u][i]] >= dep[v]) u = grand[u][i];
}
if (u == v) return u; for(int i = 20; i >= 0; i--){
if (grand[u][i] != grand[v][i]){
u = grand[u][i];
v = grand[v][i];
}
}
return grand[u][0];
} int query(int t1, int t2, int t3, int t4, int k, int l, int r){
int d = t[t[t1].l].sum+t[t[t2].l].sum-t[t[t3].l].sum-t[t[t4].l].sum;
//printf("l = %d r = %d d = %d\n", l, r, d);
if (l == r) return l;
int m = (l+r)>>1;
if (k <= d) return query(t[t1].l, t[t2].l, t[t3].l, t[t4].l, k, l, m);
else return query(t[t1].r, t[t2].r, t[t3].r, t[t4].r, k-d, m+1, r);
}
int last=0; int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
cin >> n >> m;
for(int i = 1; i <= n; i++){
scanf("%d", &pre[i]);
rank[i] = pre[i];
}
sort(rank+1, rank+1+n);
ss = unique(rank+1, rank+1+n)-rank;
int a, b;
for(int i = 1; i < n; i++){
scanf("%d%d", &a, &b);
ve[a].push_back(b), ve[b].push_back(a);
}
dep[1] = 1;
init();
dfs(1, 0); int u, v, k;
for(int i = 1; i <= m; i++){
scanf("%d%d%d", &u, &v, &k);
u ^= last;
//printf("*** u = %d v = %d\n", u, v);
int lca = getlca(u, v);
int ans = query(root[u], root[v], root[lca], root[grand[lca][0]], k, 1, n);
last = rank[ans];
//printf("*** ans = %d\n", ans);
printf("%d\n", rank[ans]);
}
return 0;
}

树上主席树 - 查询树链上第K大的更多相关文章

  1. 主席树——树链上第k大spoj COT

    首先要求第k大就想到用主席树来处理 但是不能直接用树链剖分的dfs序来维护,因为一条链对应的dfs下标可能是断开的几段,无法用权值线段树来维护 那么久维护每个点到根节点的全值线段树,结点u的权值线段树 ...

  2. ZOJ -2112 Dynamic Rankings 主席树 待修改的区间第K大

    Dynamic Rankings 带修改的区间第K大其实就是先和静态区间第K大的操作一样.先建立一颗主席树, 然后再在树状数组的每一个节点开线段树(其实也是主席树,共用节点), 每次修改的时候都按照树 ...

  3. 利用划分树求解整数区间内第K大的值

    如何快速求出(在log2n的时间复杂度内)整数区间[x,y]中第k大的值(x<=k<=y)? 其实我刚开始想的是用快排来查找,但是其实这样是不行的,因为会破坏原序列,就算另外一个数组来存储 ...

  4. G - KiKi's K-Number(树状数组求区间第k大)

    For the k-th number, we all should be very familiar with it. Of course,to kiki it is also simple. No ...

  5. 线段树专题2-(加强版线段树-可持续化线段树)主席树 orz! ------用于解决区间第k大的问题----xdoj-1216

    poj-2104(区间第K大问题) #include <iostream> #include <algorithm> #include <cstdio> #incl ...

  6. 【POJ2104】【整体二分+树状数组】区间第k大

    Description You are working for Macrohard company in data structures department. After failing your ...

  7. 【Tyvj2133&BZOJ1146】网络管理Network(树套树,DFS序,树状数组,主席树,树上差分)

    题意:有一棵N个点的树,每个点有一个点权a[i],要求在线实现以下操作: 1:将X号点的点权修改为Y 2:查询X到Y的路径上第K大的点权 n,q<=80000 a[i]<=10^8 思路: ...

  8. 可持久化线段树(主席树)——静态区间第k大

    主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...

  9. 可持久化线段树(主席树)(图文并茂详解)【poj2104】【区间第k大】

    [pixiv] https://www.pixiv.net/member_illust.php?mode=medium&illust_id=63740442 向大(hei)佬(e)实力学(di ...

随机推荐

  1. Django入门6--Django超链接

  2. http请求头包括了哪些常见内容

    Host: www.study.com                // 请求的地址域名和端口,不包括协议 Connection: keep-alive    // 连接类型,持续连接 Upgrad ...

  3. zoj 4124 "Median" (思维?假的图论?)

    传送门 来源:2019 年“浪潮杯”第十届山东省 ACM 省赛 题意: 对于一个包含n个数的(n为奇数)序列val[ ],排序后的 val[ (n+1) / 2 ] 定义为 median: 有 n 个 ...

  4. H3C 示例:计算子网地址

  5. 2018百度之星资格赛A B F

    A.调查问卷 度度熊为了完成毕业论文,需要收集一些数据来支撑他的论据,于是设计了一份包含 mm 个问题的调查问卷,每个问题只有 'A' 和 'B' 两种选项. 将问卷散发出去之后,度度熊收到了 nn  ...

  6. JavaScript 面向对象的拖拽

    一.body <div id="box"></div> 二.css <style> #box { position: abaolute; top ...

  7. op挂载摄像头

    挂载摄像头openwrt挂载ZC0301PL-USB摄像头教程http://www.openwrt.org.cn/bbs/viewthread.php?tid=30

  8. Java 学习笔记(3)——函数

    之前的几篇文章中,总结了java中的基本语句和基本数据类型等等一系列的最基本的东西,下面就来说说java中的函数部分 函数基础 在C/C++中有普通的全局函数.类成员函数和类的静态函数,而java中所 ...

  9. LeetCode111_求二叉树最小深度(二叉树问题)

    题目: Given a binary tree, find its minimum depth.The minimum depth is the number of nodes along the s ...

  10. Elasticsearch慢查询故障诊断

    最近在做ES搜索调优,看了一些lucene搜索的文档和代码,本文用于总结调优过程中学到的知识和自己的思考. 在抓到ES慢查询之后,会通过profile或者kibana的Search Profiler ...