划分树

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;
}

 

以上是关于划分树的主要内容,如果未能解决你的问题,请参考以下文章

Java 求解划分字母区间

模板划分树

CART决策树----基尼指数划分

763. 划分字母区间

Leetcode 763 划分字母区间

划分树(poj2104)