[bzoj2588][ Count on a tree]
思路
查询区间第k小,考虑主席树。因为是从u到v的简单路径上,考虑将路径分为从u到lca和从lca到v两部分。所以对于每个点都维护出从根节点到当前节点中的点。查询的时候只要用ans[u] + ans[v] - ans[lca] - ans[fa[lca]]就行了。也就是在主席树的查询代码上略加修改。
代码
/*
* @Author: wxyww
* @Date: 2018-12-11 17:19:03
* @Last Modified time: 2018-12-11 18:05:14
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<map>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<bitset>
#include<vector>
using namespace std;
typedef long long ll;
const int N = 100000 + 100,logN = 19;
vector<int>e[N];
map<int,int>ma;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int js,n,tot;
int w[N],tree[N * 30],ls[N * 30],root[N],rs[N * 30],dy[N];
int lca[N][logN + 5],dep[N];
void get_lca(int u,int father) {
for(int i = 1;i <= logN;++i)
lca[u][i] = lca[lca[u][i - 1]][i - 1];
int k = e[u].size();
for(int i = 0;i < k;++i) {
int v = e[u][i];
if(v == father) continue;
lca[v][0] = u;
dep[v] = dep[u] + 1;
get_lca(v,u);
}
}
int LCA(int x,int y) {
if(dep[x] < dep[y]) swap(x,y);
for(int i = logN;i >= 0;--i) if(dep[lca[x][i]] >= dep[y]) x = lca[x][i];
if(x == y) return x;
for(int i = logN;i >= 0;--i) if(lca[x][i] != lca[y][i]) x = lca[x][i],y = lca[y][i];
return lca[x][0];
}
void update(int &rt,int lst,int l,int r,int pos) {
rt = ++tot;
ls[rt] = ls[lst];rs[rt] = rs[lst];
tree[rt] = tree[lst] + 1;
if(l == r) return;
int mid = (l + r) >> 1;
if(pos <= mid) update(ls[rt],ls[lst],l,mid,pos);
else update(rs[rt],rs[lst],mid + 1,r,pos);
}
int query(int L,int R,int Lca,int falca,int k,int l,int r) {
int z = tree[ls[L]] + tree[ls[R]] - tree[ls[Lca]] - tree[ls[falca]];//与普通主席树不同的地方
if(l == r) return l;
int mid = (l + r) >> 1;
if(k <= z) return query(ls[L],ls[R],ls[Lca],ls[falca],k,l,mid);
else return query(rs[L],rs[R],rs[Lca],rs[falca],k - z,mid + 1,r);
}
void dfs(int u,int father) {
int k = e[u].size();
update(root[u],root[father],1,js,w[u]);
for(int i = 0;i < k;++i) {
int v = e[u][i];
if(v == father) continue;
dfs(v,u);
}
}
int main() {
n = read();int m = read();
for(int i = 1;i <= n;++i) ls[i] = w[i] = read();
sort(ls + 1,ls + n + 1);
ma[ls[1]] = ++js;
dy[js] = ls[1];
for(int i = 2; i <= n;++i) if(ls[i] != ls[i - 1]) ma[ls[i]] = ++js,dy[js] = ls[i];
for(int i = 1;i <= n;++i) w[i] = ma[w[i]];
for(int i = 1;i < n;++i) {
int u = read(),v = read();
e[u].push_back(v);e[v].push_back(u);
}
dfs(1,0);
dep[1] = 1;
get_lca(1,0);
int LST = 0;
while(m--) {
int l = read() ^ LST,r = read(),k = read();
int z = LCA(l,r);
// printf("%d %d %d\n",l,r,z);
LST = dy[query(root[l],root[r],root[z],root[lca[z][0]],k,1,js)];
printf("%d\n",LST);
}
return 0;
}
===================================================================================
该怎麼去形容为思念酝酿的痛
夜空霓虹都是我不要的繁荣 ===================================================================================