划分树
Posted 小小八
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了划分树相关的知识,希望对你有一定的参考价值。
POJ 2214 裸的划分树求区间第k大值
//POJ 2104 #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #define maxn 100010 using namespace std; int tree[30][maxn]; int sorted[maxn]; int toleft[30][maxn]; void build(int l, int r, int dep) { if (l == r) return; int mid = (l+r) >> 1; int same = mid - l + 1; for (int i=l; i<=r; ++i) if (tree[dep][i] < sorted[mid]) same--; int lpos = l; int rpos = mid+1; for (int i=l; i<=r; ++i) { if (tree[dep][i] < sorted[mid]) tree[dep+1][lpos++] = tree[dep][i]; else if (tree[dep][i] == sorted[mid] && same>0) { tree[dep+1][lpos++] = tree[dep][i]; same--; }else tree[dep+1][rpos++] = tree[dep][i]; toleft[dep][i] = toleft[dep][l-1]+lpos-l; } build(l, mid, dep+1); build(mid+1, r, dep+1); } int query(int L, int R, int l, int r, int dep, int k) { if (l == r) return tree[dep][l]; int mid = (L+R)>>1; int cnt = toleft[dep][r] - toleft[dep][l-1]; if (cnt >= k) { int newl = L+toleft[dep][l-1]-toleft[dep][L-1]; int newr = newl+cnt-1; return query(L, mid, newl, newr, dep+1, k); }else { int newr = r+toleft[dep][R]-toleft[dep][r]; int newl = newr-(r-l-cnt); return query(mid+1, R, newl, newr, dep+1, k-cnt); } } int main() { // freopen("in.cpp", "r", stdin); int n, m; while(~scanf("%d%d", &n, &m)) { for (int i=1; i<=n; ++i) { scanf("%d", &tree[0][i]); sorted[i] = tree[0][i]; } sort(sorted+1, sorted+1+n); build(1, n, 0); while(m--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); printf("%d\n", query(1, n, a, b, 0, c)); } } return 0; }
HDU 4417 二分+划分树
//HDU 4417 #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; const int maxn = 1e5+10; int tree[30][maxn]; int toleft[30][maxn]; int sorted[maxn]; void build(int l, int r, int dep) { if (l == r) return; int mid = (l+r) >> 1; int same = mid - l + 1; for (int i=l; i<=r; ++i) if (tree[dep][i] < sorted[mid]) same--; int lpos = l; int rpos = mid+1; for (int i=l; i<=r; ++i) { if (tree[dep][i] < sorted[mid]) tree[dep+1][lpos++] = tree[dep][i]; else if (tree[dep][i] == sorted[mid] && same>0) { tree[dep+1][lpos++] = tree[dep][i]; same--; }else tree[dep+1][rpos++] = tree[dep][i]; toleft[dep][i] = toleft[dep][l-1]+lpos-l; } build(l, mid, dep+1); build(mid+1, r, dep+1); } int query(int L, int R, int l, int r, int dep, int k) { if (l == r) return tree[dep][l]; int mid = (L+R)>>1; int cnt = toleft[dep][r] - toleft[dep][l-1]; if (cnt >= k) { int newl = L+toleft[dep][l-1]-toleft[dep][L-1]; int newr = newl+cnt-1; return query(L, mid, newl, newr, dep+1, k); }else { int newr = r+toleft[dep][R]-toleft[dep][r]; int newl = newr-(r-l-cnt); return query(mid+1, R, newl, newr, dep+1, k-cnt); } } int solve(int n, int a, int b, int c) { int ans = 0; int l = 1; int r = b - a + 1; int mid; while(l<=r) { mid = (l+r)>>1; int temp = query(1, n, a, b, 0, mid); if (temp <= c) { l = mid+1; ans = mid; }else r = mid - 1; } return ans; } int main() { // freopen("in.cpp", "r", stdin); int t; int k = 0; scanf("%d", &t); while(t--) { int n, m; scanf("%d%d", &n, &m); memset(toleft, 0, sizeof(toleft)); memset(tree, 0, sizeof(tree)); for (int i=1; i<=n; ++i) { scanf("%d", &tree[0][i]); sorted[i] = tree[0][i]; } sort(sorted+1, sorted+1+n); build(1, n, 0); printf("Case %d:\n", ++k); for (int i=0; i<m; ++i) { int a, b, c; scanf("%d%d%d",&a, &b, &c); a++; b++; int ans = solve(n, a, b, c); printf("%d\n", ans); } } return 0; }
以上是关于划分树的主要内容,如果未能解决你的问题,请参考以下文章