1. 程式人生 > >[BZOJ 1803] Query on a tree III

[BZOJ 1803] Query on a tree III

[題目連結]

          https://www.lydsy.com/JudgeOnline/problem.php?id=1803

[演算法]

        首先 , 一棵子樹的DFS序必然為連續的一段

        通過這個性質 , 我們將一個樹上的問題轉化為了一個序列上的問題

        可持久化線段樹可以解決該問題 , 不再贅述

        時間複雜度 : O(MlogN)

[程式碼]

        

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 10;

struct edge
{
        int to , nxt;
} e[MAXN << 2];

int tot , n , m , timer , idx;
int root[MAXN] , dfn[MAXN] , size[MAXN] , head[MAXN] , a[MAXN] , order[MAXN] , tmp[MAXN] , loc[MAXN] , lson[MAXN * 40
] , rson[MAXN * 40] , sum[MAXN * 40]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for
(; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedge(int x , int y) { ++tot; e[tot] = (edge){y , head[x]}; head[x] = tot; } inline bool cmp(int x , int y) { return dfn[x] < dfn[y]; } inline void dfs(int u , int fa) { dfn[u] = ++timer; size[u] = 1; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v == fa) continue; dfs(v , u); size[u] += size[v]; } } inline void build(int &k , int l , int r) { k = ++idx; if (l == r) return; int mid = (l + r) >> 1; build(lson[k] , l , mid); build(rson[k] , mid + 1 , r); } inline void modify(int &k , int old , int l , int r , int pos , int value) { k = ++idx; lson[k] = lson[old] , rson[k] = rson[old]; sum[k] = sum[old] + value; if (l == r) return; int mid = (l + r) >> 1; if (mid >= pos) modify(lson[k] , lson[k] , l , mid , pos , value); else modify(rson[k] , rson[k] , mid + 1 , r , pos , value); } inline int query(int rt1 , int rt2 , int l , int r , int k) { if (l == r) return l; int mid = (l + r) >> 1; if (sum[lson[rt1]] - sum[lson[rt2]] >= k) return query(lson[rt1] , lson[rt2] , l , mid , k); else return query(rson[rt1] , rson[rt2] , mid + 1 , r , k - (sum[lson[rt1]] - sum[lson[rt2]])); } int main() { read(n); for (int i = 1; i <= n; i++) { read(a[i]); tmp[i] = a[i]; } sort(tmp + 1 , tmp + n + 1); for (int i = 1; i <= n; i++) { int l = 1 , r = n , pos; while (l <= r) { int mid = (l + r) >> 1; if (tmp[mid] >= a[i]) { pos = mid; r = mid - 1; } else l = mid + 1; } a[i] = pos; loc[pos] = i; } for (int i = 1; i < n; i++) { int x , y; read(x); read(y); addedge(x , y); addedge(y , x); } dfs(1 , 0); for (int i = 1; i <= n; i++) order[i] = i; sort(order + 1 , order + n + 1 , cmp); build(root[0] , 1 , n); for (int i = 1; i <= n; i++) modify(root[i] , root[i - 1] , 1 , n , a[order[i]] , 1); read(m); while (m--) { int u , k; read(u); read(k); printf("%d\n" , loc[query(root[dfn[u] + size[u] - 1] , root[dfn[u] - 1] , 1 , n , k)]); } return 0; }