poj2104(划分树模板)
生活随笔
收集整理的這篇文章主要介紹了
poj2104(划分树模板)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
poj2104
題意
給出一個序列,每次查詢一個區間,要求告訴這個區間排序后的第k個數。
分析
劃分樹模板,O(mlogn)。
code
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; typedef long long ll; const int INF = 1e9; const int MAXN = 1e5 + 5; const int LOG_N = 30; // tree[dep][i] 第dep層第i個位置的數值 int tree[LOG_N][MAXN]; int sorted[MAXN]; // toleft[p][i] 第p層前i個數中有多少個整數分入下一層 int toleft[LOG_N][MAXN];void build(int l, int r, int dep) {if(l == r) return;int mid = (l + r) / 2;int same = mid - l + 1; // 和中點數相同的數的個數for(int i = l; i <= r; i++)if(tree[dep][i] < sorted[mid]) same--;int lpos = l, 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){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); } // [L,R]里查詢子區間[l,r]第k小的數 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) / 2;// 有多少個查詢區間內的節點會進入下一層的左子樹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() {int n, m;while(~scanf("%d%d", &n, &m)){for(int i = 1; i <= n; i++){scanf("%d", &sorted[i]);tree[0][i] = sorted[i];}sort(sorted + 1, sorted + n + 1);build(1, n, 0);while(m--){int l, r, k;scanf("%d%d%d", &l, &r, &k);printf("%d\n", query(1, n, l, r, 0, k));}}return 0; }轉載于:https://www.cnblogs.com/ftae/p/6872804.html
總結
以上是生活随笔為你收集整理的poj2104(划分树模板)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [BZOJ 4551][Tjoi2016
- 下一篇: Ruby Fiber指南(三)过滤器