日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ-2588-Count-on-a-tree-SPOJ10628-LCA+主席树

發布時間:2025/3/15 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ-2588-Count-on-a-tree-SPOJ10628-LCA+主席树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

描述

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


分析

  • 想用樹鏈剖分但是發現不知道怎么套主席樹.
  • 正解是LCA, 只要維護根節點到每個結點u的權值線段樹. 因為主席樹求第k大支持減法, 所以最終答案就是線段樹 u+v-lca(u,v)-fa[lca(u,v)] 中的第k大.
  • 調了半天發現在用lower_bound查找離散后的權值時, unique后的T數組有序不假但重復元素被挪到了數組尾, 所以不能再用原來的T+n+1作為二分查找的上界了.

#include #include #include using namespace std;const int maxn = 100000 + 10; const int maxm = 3000000; const int DEP = 20;vectorG[maxn];int n, m, tot, node_cnt; int A[maxn], T[maxn]; int dep[maxn], fa[maxn][DEP]; int root[maxm], lc[maxm], rc[maxm], s[maxm];#define M (L+R>>1)void modify(int& x, int y, int L, int R, int d) {x = ++node_cnt;lc[x] = lc[y]; rc[x] = rc[y]; s[x] = s[y] + 1;if(L == R) return;if(d <= M) modify(lc[x], lc[y], L, M, d);else modify(rc[x], rc[y], M+1, R, d); }int query(int u, int v, int x, int y, int L, int R, int k) {if(L == R) return L;int ls = s[lc[u]] + s[lc[v]] - s[lc[x]] - s[lc[y]];if(k <= ls) return query(lc[u], lc[v], lc[x], lc[y], L, M, k);return query(rc[u], rc[v], rc[x], rc[y], M+1, R, k-ls); }void dfs(int u, int x) {dep[u] = dep[fa[u][0] = x] + 1;for(int i = 1; i < DEP; i++)if((1<<= dep[u]) fa[u][i] = fa[fa[u][i-1]][i-1]; else break; modify(root[u], root[x], 1, tot, A[u]); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(v != x) dfs(v, u); } } int lca(int x, int y) { if(dep[x] < dep[y]) swap(x, y); int delta = dep[x]-dep[y]; for(int i = 0; i < DEP; i++) if(delta&(1<= 0; i--) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; return fa[x][0]; } int main() { int n, m; scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d", &A[i]); T[i] = A[i]; } sort(T+1, T+n+1); tot = unique(T+1, T+n+1) - T-1; for(int i = 1; i <= n; i++) A[i] = lower_bound(T+1, T+tot+1, A[i]) - T; for(int i = 1; i < n; i++) { int u, v; scanf("%d %d", &u, &v); G[u].push_back(v); G[v].push_back(u); } dfs(1, 0); int ans = 0; for(int i = 1; i <= m; i++) { int u, v, k; scanf("%d %d %d", &u, &v, &k); u ^= ans; int x = lca(u, v), y = fa[x][0]; ans = T[query(root[u], root[v], root[x], root[y], 1, tot, k)]; if(i < m) printf("%d\n", ans); else printf("%d", ans); } return 0; }


與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的BZOJ-2588-Count-on-a-tree-SPOJ10628-LCA+主席树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。