而树上第K大,依旧是每个结点一棵主席树,是在父节点的基础上修改。
这里用了倍增法求lca
这代码要跑2900MS左右。。
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> #include <algorithm> using namespace std; const int N = 200010; const int M = N * 40; int n,m,q,tot; int a[N],t[N]; int T[N],ls[M],rs[M],c[M],d[N],fa[N][27]; vector<int> vec[N]; void init(){ memset(fa, -1, sizeof(fa)); tot = 0; } void Init_hash(){ for(int i = 1; i<= n; i++){ t[i] = a[i]; } sort(t+1,t+n+1); m = unique(t+1,t+1+n)-t-1; } void build(int l, int r, int &rt){ rt = tot ++; c[rt] = 0; if(l != r){ int mid = (l+r)>>1; build(l, mid, ls[rt] ); build(mid+1, r, rs[rt]); } } int hash(int x){ return lower_bound(t+1,t+1+m,x)-t; } int update(int root, int pos, int val){//循环 int newroot = tot++, tmp = newroot; c[newroot] = c[root] + val; int l = 1, r = m; while(l < r){ int mid = (l+r)>>1; if(pos <= mid){ ls[newroot] = tot++; rs[newroot] = rs[root]; newroot = ls[newroot]; root = ls[root]; r = mid; } else { rs[newroot] = tot++; ls[newroot] = ls[root]; newroot = rs[newroot]; root = rs[root]; l = mid+1; } c[newroot] = c[root] + val; } return tmp; } void update2(int last, int pos, int l, int r, int& rt){//递归 rt = ++ tot; ls[rt] = ls[last], rs[rt] = rs[last], c[rt] = c[last] + 1; if (l == r) return ; int mid = (l + r) >> 1; if (pos <= mid) update2(ls[last], pos, l, mid, ls[rt]); else update2(rs[last], pos, mid + 1, r, rs[rt]); } int query(int lrt, int rrt, int lca, int k){//循环 int lcart = T[lca], pos = hash(a[lca]); int l = 1, r = m; while(l < r){ int mid = (l+r)>>1; int cot = c[ls[lrt]] + c[ls[rrt]] - 2*c[ls[lcart]] + (pos >= l && pos <=mid); if(cot >= k){ r = mid; lrt = ls[lrt]; rrt = ls[rrt]; lcart = ls[lcart]; } else { l = mid+1; k -= cot; lrt = rs[lrt]; rrt = rs[rrt]; lcart = rs[lcart]; } } return l; } int query2(int pos, int left_rt, int right_rt, int lca_rt, int l, int r, int k){//递归 if (l == r) return l; int mid = (l + r) >> 1; int cnt = c[ls[left_rt]] + c[ls[right_rt]] - 2 * c[ls[lca_rt]] + (pos >= l && pos <= mid); if (k <= cnt) return query2(pos, ls[left_rt], ls[right_rt], ls[lca_rt], l, mid, k); else return query2(pos, rs[left_rt], rs[right_rt], rs[lca_rt], mid + 1, r, k - cnt); } void dfs_build(int u, int pre){ fa[u][0] = pre; d[u] = d[pre] + 1; int pos = hash(a[u]); T[u] = update(T[pre], pos, 1); //update2(T[pre], pos, 1, m, T[u]); int sz = vec[u].size(); for(int i = 0; i < sz; i++){ int v = vec[u][i]; if(v != pre){ dfs_build(v, u); } } } void init_fa(){ for(int j = 1; (1<<j) <= n; j++){ for(int i = 1; i <= n; i++){ fa[i][j] = fa[fa[i][j-1]][j-1]; } } } int LCA(int a, int b){ int i, j; if(d[a] < d[b])swap(a, b); for(i = 0; (1<<i) <= d[a]; i++);i--; for( j = i; j >= 0; j--){ if(d[a] - (1<<j) >= d[b]) a = fa[a][j]; } if(a == b)return a; for(j = i; j >= 0; j--){ if(fa[a][j] != -1 && fa[a][j] != fa[b][j]){ a = fa[a][j], b = fa[b][j]; } } return fa[a][0]; } int main(){ int u,v,k; //freopen("in.txt","r",stdin); while(~scanf("%d%d", &n, &q)){ init(); for(int i = 1; i <= n; i++ )scanf("%d", a+i); for(int i = 1; i < n; i++){ scanf("%d%d", &u, &v); vec[u].push_back(v); vec[v].push_back(u); } Init_hash(); build(1, m, T[0]); dfs_build(1, 0); init_fa(); while(q--){ scanf("%d%d%d", &u, &v, &k); int lca = LCA(u, v); printf("%d\n",t[query(T[u],T[v],lca,k)]); //printf("%d\n",t[query2(hash(a[lca]), T[u], T[v], T[lca],1, m, k)]); } for(int i = 1; i <= n; i++)vec[i].clear(); } return 0; }