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. POI 导入、导出Excel

    POI,全称Apache POI,是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能.项目地址:Apache POI - t ...

  2. python编程设计模式之接口类和抽象类

    接口类 """ 接口类 是一种编程设计模式,在python原本没有接口类 借用Java思想创建的一种规范设计模式 支持多继承,进行多方面规范 ""&q ...

  3. python基础七之集合

    集合:可变的数据类型,他里面的元素必须是不可变的数据类型,无序,不重复. 增加 set1 = {'zxc', 'zxf'} set1.add('zxv') # 无序添加 set1.update('zx ...

  4. linux ioctl 方法

    ioctl, 我们在第 1 章展示给你如何使用, 是一个系统调用, 作用于一个文件描述符; 它 接收一个确定要进行的命令的数字和(可选地)另一个参数, 常常是一个指针. 作为一个使 用 /proc 文 ...

  5. linux 让出处理器

    如我们已见到的, 忙等待强加了一个重负载给系统总体; 我们乐意找出一个更好的技术. 想到的第一个改变是明确地释放 CPU 当我们对其不感兴趣时. 这是通过调用调度函数而 实现地, 在 <linu ...

  6. js快速替换json里的key值

    需求是将b根据a的值替换对象中的key值 let a = ["code","name","date","font"]; ...

  7. PowerShell 通过 WMI 获取系统安装的驱动

    本文告诉大家如何通过 WMI 获取用户已经安装的驱动程序 通过下面代码可以获取用户已经安装的驱动程序 Get-WmiObject Win32_SystemDriver | Format-List Ca ...

  8. git 通过 SublimeMerge 处理冲突

    在使用 Git 的时候,如果是多个小伙伴开发,那么如果同时修改一个文件将出现冲突.也就是在自动合并的时候不知道使用哪个代码才对,此时就需要合并工具的协助.我找了很久发现 SublimeMerge 是界 ...

  9. [板子]Kruskal

    众所周知求最小生成树的两种方法: 1.Kruskal 2.Prim 这里只挂第一种,因为noip掌握第一种就够了. 两种做法的区别可以参考这个博客:http://blog.csdn.net/molln ...

  10. Hadoop Authentication

    我被被派去做别的事情了,所以与hadoop相关的工作就只能搁下.写篇总结,把最近遇到的和kerberos相关的东西列一下. JAAS是Java 认证和授权服务(Java Authentication ...