1. 程式人生 > >[bzoj2588][ Count on a tree]

[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;
}