樹上主席樹 查詢樹鏈上第K大

2022-06-27 05:36:14 字數 1738 閱讀 9962

給定一棵n個節點的樹,每個點有乙個權值,對於m個詢問(u,v,k),你需要回答u xor lastans和v這兩個節點間第k小的點權。其中lastans是上乙個詢問的答案,初始為0,即第乙個詢問的u是明文。

第一行兩個整數n,m。

第二行有n個整數,其中第i個整數表示點i的權值。

後面n-1行每行兩個整數(x,y),表示點x到點y有一條邊。

最後m行每行兩個整數(u,v,k),表示一組詢問。

m行,表示每個詢問的答案。最後乙個詢問不輸出換行符

8 5105 2 9 3 8 5 7 7

1 21 3

1 43 5

3 63 7

4 82 5 1

0 5 2

10 5 3

11 5 4

110 8 228

9105

7 n,m<=100000

暴力自重。。。

思路分析 :還是利用主席樹,在樹上建立主席樹,從根節點到當前節點建立線段樹,借助 lca, 然後比如要查詢 u, v 這段區間,要先找到u, v 之間的公共祖先 lca

**示例 :

#define ll long long

const int maxn = 1e5+5;

const int mod = 1e9+7;

const double eps = 1e-9;

const double pi = acos(-1.0);

const int inf = 0x3f3f3f3f;

int n, m;

int pre[maxn], rank[maxn];

vectorve[maxn];

int dep[maxn];

int grand[maxn][22];

int root[maxn];

int cnt, ss;

struct node

t[maxn*20];

void update(int num, int &rt, int l, int r)

void dfs(int x, int fa)

int num = lower_bound(rank+1, rank+ss, pre[x])-rank;

root[x] = root[fa];

update(num, root[x], 1, n);

for(int i = 0; i < ve[x].size(); i++)

}void init()

int getlca(int u, int v)

if (u == v) return u;

for(int i = 20; i >= 0; i--)

}return grand[u][0];

}int query(int t1, int t2, int t3, int t4, int k, int l, int r)

int last=0;

int main()

sort(rank+1, rank+1+n);

ss = unique(rank+1, rank+1+n)-rank;

int a, b;

for(int i = 1; i < n; i++)

dep[1] = 1;

init();

dfs(1, 0);

int u, v, k;

for(int i = 1; i <= m; i++)

return 0;

}

SPOJ COT 樹上第K大 LCA 主席樹

這題和普通的第k大類似。普通的第k大,是從後往前建立主席樹,前乙個在後乙個的基礎上修改。而樹上第k大,依舊是每個結點一棵主席樹,是在父節點的基礎上修改。那麼可以發現這棵主席樹是包括所有祖先結點的 就是深度在當前結點之上的 查詢的時候,是兩個結點的值的和,還要減掉lca以上的部分。同時要注意處理lca...

區間第k大(主席樹)

學了一下主席樹模板題,當初看了網上的主席樹講解都沒有看懂,後面看了嗶哩嗶哩的uestc的主席樹,終於看懂了思想。每次更新的複雜度都為logn。每次更新的話就是對要更新的點路徑上的點重新更加乙個,然後進行對沒有影響的那些進行連邊。然後用乙個root記錄每乙個線段樹的根節點下標。include incl...

主席樹區間第K大

主席樹的實質其實還是一顆線段樹,然後每一次修改都通過上一次的線段樹,來新增新邊,使得每次改變就改變logn個節點,很多節點重複利用,達到節省空間的目的。1.不帶修改的區間第k大。hdu 2665 模板題 1 include2 using namespace std 3 define fopen fr...