概述
求区间第k大!也可以用主席树,过几天去搞下主席树吧!
直接上板子
/*
* 划分树(查询区间第 k 大)
// toleft[p][i] 表示第 i 层从 1 到 i 有数分入左边
// sorted[MAX_SIZE]; 已经排好序的数据
// tree[25][MAX_SIZE]; tree[i][n] 表示的是第i层有n个数字
*/
const int MAX_SIZE = 100005;
int sorted[MAX_SIZE];
int toleft[25][MAX_SIZE];
int tree[25][MAX_SIZE];
void build_tree(int left, int right, int deep)
{
int i;
if (left == right) return ;
int mid = (left + right) >> 1;
int same = mid - left + 1; //位于左子树的数据
for (i = left; i <= right; ++i) { //计算放于左子树中与中位数相等的数字个数
if (tree[deep][i] < sorted[mid]) {
--same;
}
}
int ls = left;
int rs = mid + 1;
for (i = left; i <= right; ++i) {
int flag = 0;
if ((tree[deep][i] < sorted[mid]) || (tree[deep][i] == sorted[mid] && same > 0)) {
flag = 1;
tree[deep + 1][ls++] = tree[deep][i];
if (tree[deep][i] == sorted[mid])
same--;
} else {
tree[deep + 1][rs++] = tree[deep][i];
}
toleft[deep][i] = toleft[deep][i - 1]+flag;
}
build_tree(left, mid, deep + 1);
build_tree(mid + 1, right, deep + 1);
}
int query(int left, int right, int k, int L, int R, int deep)
{
if (left == right)
return tree[deep][left];
int mid = (L + R) >> 1;
int x = toleft[deep][left - 1] - toleft[deep][L - 1];//位于left左边的放于左子树中的数字个数
int y = toleft[deep][right] - toleft[deep][L - 1];//到right为止位于左子树的个数
int ry = right - L - y;//到right右边为止位于右子树的数字个数
int cnt = y - x;//[left,right]区间内放到左子树中的个数
int rx = left - L - x;//left左边放在右子树中的数字个数
if (cnt >= k) {
//printf("sss %d %d %dn", xx++, x, y);
return query(L + x, L + y - 1, k, L, mid, deep + 1);
// 因为x不在区间内 所以没关系 所以先除去,从L+x开始,然后确定范围
}
else {
//printf("qqq %d %d %dn", xx++, x, y);
return query(mid + rx + 1, mid + 1 + ry, k - cnt, mid + 1, R, deep + 1);
//同理 把不在区间内的 分到右子树的元素数目排除,确定范围
}
}
void solve(){
int n, m;
int l, r, k;
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 + 1 + n);
build_tree(1, n, 0);
for(int i = 0; i < m; i++){
scanf("%d%d%d", &l, &r, &k);
int ans = query(l, r, k, 1, n, 0);
printf("%dn",ans);
}
}
int main()
{
int t;
scanf("%d",&t);
//t = 1;
while(t--){
solve();
}
return 0;
}
先来个板子题:
题目传送门:POJ2104
**题意:**直接裸!静态求区间第k大
我的理解: 直接上板子
直接上板子
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<string>
#include<set>
#define sa(t) scanf("%d",&t)
#define SA(t) scanf("%lld", %t)
#define PF(t) printf("%lld",t)
#define pf(t) printf("%d", t)
#define PFF(t) printf("%lldn",t)
#define pff(t) printf("%dn", t)
using namespace std;
/*
* 划分树(查询区间第 k 大)
//toleft[p][i] 表示第 i 层从 1 到 i 有数分入左边
// sorted[MAX_SIZE]; 已经排好序的数据
// tree[25][MAX_SIZE]; tree[i][n] 表示的是第i层有n个数字
*/
const int MAX_SIZE = 100005;
int sorted[MAX_SIZE];
int toleft[25][MAX_SIZE];
int tree[25][MAX_SIZE];
void build_tree(int left, int right, int deep)
{
int i;
if (left == right) return ;
int mid = (left + right) >> 1;
int same = mid - left + 1;
for (i = left; i <= right; ++i) {
if (tree[deep][i] < sorted[mid]) {
--same;
}
}
int ls = left;
int rs = mid + 1;
for (i = left; i <= right; ++i) {
int flag = 0;
if ((tree[deep][i] < sorted[mid]) || (tree[deep][i] == sorted[mid] && same > 0)) {
flag = 1;
tree[deep + 1][ls++] = tree[deep][i];
if (tree[deep][i] == sorted[mid])
same--;
} else {
tree[deep + 1][rs++] = tree[deep][i];
}
toleft[deep][i] = toleft[deep][i - 1]+flag;
}
build_tree(left, mid, deep + 1);
build_tree(mid + 1, right, deep + 1);
}
int query(int left, int right, int k, int L, int R, int deep)
{
if (left == right)
return tree[deep][left];
int mid = (L + R) >> 1;
int x = toleft[deep][left - 1] - toleft[deep][L - 1];
int y = toleft[deep][right] - toleft[deep][L - 1];
int ry = right - L - y;
int cnt = y - x;
int rx = left - L - x;
if (cnt >= k) {
return query(L + x, L + y - 1, k, L, mid, deep + 1);
}
else {
return query(mid + rx + 1, mid + 1 + ry, k - cnt, mid + 1, R, deep + 1);
}
}
void solve(){
int n, m;
int l, r, k;
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 + 1 + n);
build_tree(1, n, 0);
for(int i = 0; i < m; i++){
scanf("%d%d%d", &l, &r, &k);
int ans = query(l, r, k, 1, n, 0);
printf("%dn",ans);
}
}
int main()
{
int t;
//scanf("%d",&t);
t = 1;
while(t--){
solve();
}
return 0;
}
持续更新中!!!
最后
以上就是虚拟麦片为你收集整理的(数据结构)划分树(查询区间第 k 大)和题库的全部内容,希望文章能够帮你解决(数据结构)划分树(查询区间第 k 大)和题库所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复