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. P1100 三连击

    题目描述 我们假设一个三位整数 \(N(100 \le N \le 999)\) ,它的百位上的数字是 \(A\) ,十位上的数字是 \(B\) ,个位上的数字是 \(C\) ,如果 \(A\) , ...

  2. 基于串口调试助手的WIFI模块调试-FPGA简单联网(点灯)

    根据正点原子的<ATK-ESP8266 WIFI用户手册>,使用XCOM V2.2串口调试助手测试WIFI模块[26].在本系统中运用到的功能主要是TCP/IP模式中的TCP Client ...

  3. P1037 最小公倍数

    题目描述 给你两个正整数A和B,求它们的最小公倍数. 输入格式 两个正整数 \(A,B(1 \le A,B \le 10^9)\) . 输出格式 一个整数,表示A和B的最小公倍数. 样例输入 6 8 ...

  4. P1016 高精度除法

    题目描述 给你两个很大的正整数A和B,你需要计算A除以B的商和余数. 输入格式 输入一行包含两个正整数A和B,以一个空格分隔(A和B的位数都不超过 \(10^5\)) 输出格式 输出一行包含两个整数, ...

  5. vue 模块化 路由拆分配置

    一.普通路由配置 通常我们编写vue路由配置都会写在 /src/router/index.js 这个文件下.但是,随着我们的vue项目变得越来越大后,路由也随之变得越来越多,出现的问题就是我们所有的路 ...

  6. 修改github上的项目语言类型

    当在github上上传一个项目时,可能会出现一个问题就是项目代码类型是自动生成的,可能与我们实际项目代码种类不匹配,此时就需要修改项目语言类型了. 由于无法直接更改,所以用到此方法: 在你的项目根目录 ...

  7. 2018.11.9浪在ACM集训队第四次测试赛

    2018.11.9浪在ACM集训队第四次测试赛 整理人:朱远迪 A 生活大爆炸版 石头剪刀布           参考博客:[1] 刘凯 B 联合权值            参考博客: [1]田玉康 ...

  8. 牛客多校第三场 F Planting Trees

    牛客多校第三场 F Planting Trees 题意: 求矩阵内最大值减最小值大于k的最大子矩阵的面积 题解: 矩阵压缩的技巧 因为对于我们有用的信息只有这个矩阵内的最大值和最小值 所以我们可以将一 ...

  9. geoip ip2region2 with spark

    上一篇文章中 我使用 maxmind的免费库开发了一个waterdrop的 插件,测试数据发现,国内的有些市级还是不准确,而且香港并不是显示中国,这就不友好了. 找了一下,发下 ip2region 这 ...

  10. lumen简单使用exel组件

    1.首先打开命令行,进入到lumen项目的根目录中,然后用composer下载excel组件 composer require maatwebsite/excel ~2.1.0 2.安装成功后,在bo ...