日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

poj2104(划分树模板)

發布時間:2025/3/21 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poj2104(划分树模板) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

poj2104

題意

給出一個序列,每次查詢一個區間,要求告訴這個區間排序后的第k個數。

分析

劃分樹模板,O(mlogn)。

  • 建樹。根據排序之后的數組,對于一個區間,找到中點的數,將整個區間分為左右子樹(在子區間內數與數的相對位置保持不變),遞歸向下分割。
  • 查詢。toleft[p][i] 表示第 p 層前 i 個數中有多少個整數分入下一層。查詢最重要的是確定新的查詢區間,若遞歸查詢左區間,則新的子區間的左邊一定是上一層區間 [L, l - 1] 里的 toleft[dep][l-1] - toleft[dep][L-1] 個整數,那么 newl = L + toleft[dep][l-1] - toleft[dep][L-1],[l, r] 區間內有cnt = toleft[dep][r] - toleft[dep][l - 1] 個數,所以 newr = newl + cnt - 1;查詢右區間則要先確定 newr 的值,[r+1, R] 中有 c = toleft[dep][R] - toleft[dep][r] 個整數位于左子區間的右方,所以查詢區間 r 要向右移 c 個數,newr = r + c,newl = newr - (r - l - cnt)。
  • 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(划分树模板)的全部內容,希望文章能夠幫你解決所遇到的問題。

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