# [BZOJ2588][Spoj 10628]Count on a tree

[BZOJ2588][Spoj 10628]Count on a tree

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

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

2
8
9
105
7

N,M<=100000

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std;

const int BufferSize = 1 << 16;
inline char Getchar() {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
}
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
}

#define maxn 100010
#define maxm 200010
#define maxlog 17
#define maxnode 2000010
int n, rt[maxn], val[maxn], num[maxn];

int ToT, sumv[maxnode], lc[maxnode], rc[maxnode];
void update(int& y, int x, int l, int r, int p) {
sumv[y = ++ToT] = sumv[x] + 1;
if(l == r) return ;
int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
if(p <= mid) update(lc[y], lc[x], l, mid, p);
else update(rc[y], rc[x], mid + 1, r, p);
return ;
}

int m, head[maxn], next[maxm], to[maxm], fa[maxlog][maxn], dep[maxn];
void AddEdge(int a, int b) {
swap(a, b);
return ;
}
void build(int u) {
update(rt[u], rt[fa[0][u]], 1, n, val[u]);
for(int i = 1; i < maxlog; i++) fa[i][u] = fa[i-1][fa[i-1][u]];
for(int e = head[u]; e; e = next[e]) if(to[e] != fa[0][u]) {
fa[0][to[e]] = u;
dep[to[e]] = dep[u] + 1;
build(to[e]);
}
return ;
}
int lca(int a, int b) {
if(dep[a] < dep[b]) swap(a, b);
for(int i = maxlog - 1; i >= 0; i--) if(dep[a] - dep[b] >= (1 << i)) a = fa[i][a];
for(int i = maxlog - 1; i >= 0; i--) if(fa[i][a] != fa[i][b]) a = fa[i][a], b = fa[i][b];
return a == b ? a : fa[0][b];
}

int solve(int a, int b, int k) {
int lrt[2] = {rt[a], rt[b]}, c = lca(a, b), rrt[2] = {rt[c], rt[fa[0][c]]};
int l = 1, r = n;
while(l < r) {
int mid = l + r >> 1, sum = 0;
for(int i = 0; i < 2; i++) if(lrt[i] && lc[lrt[i]]) sum += sumv[lc[lrt[i]]];
for(int i = 0; i < 2; i++) if(rrt[i] && lc[rrt[i]]) sum -= sumv[lc[rrt[i]]];
if(sum < k) {
k -= sum; l = mid + 1;
for(int i = 0; i < 2; i++) if(lrt[i]) lrt[i] = rc[lrt[i]];
for(int i = 0; i < 2; i++) if(rrt[i]) rrt[i] = rc[rrt[i]];
}
else {
r = mid;
for(int i = 0; i < 2; i++) if(lrt[i]) lrt[i] = lc[lrt[i]];
for(int i = 0; i < 2; i++) if(rrt[i]) rrt[i] = lc[rrt[i]];
}
}
return num[l];
}

int main() {
for(int i = 1; i <= n; i++) val[i] = num[i] = read();
sort(num + 1, num + n + 1);
for(int i = 1; i <= n; i++) val[i] = lower_bound(num + 1, num + n + 1, val[i]) - num;
for(int i = 1; i < n; i++) {
}
build(1);
int lst = 0;
while(q--) {