POJ 2104为例【经典划分树问题】

思想:

利用快速排序思想,

  • 建树时将区间内的值与区间中值相比,小于则放入左子树,大于则放入右子树,如果相等则放入左子树直到放满区间一半。
  • 查询时,在建树过程中利用leftsum[p][i]数组保存有多少个数划分到第p层,第i个位置的左边。每次查询计算出每个区间有多少数被放入左子树,小于等于k则说明所求数在左子树,继续查询其左子树,反之则查询右子树。l==r时则找到。
  • 时间复杂度O(nlogn+mlogn)

代码:

#include<cstdio>
#include<algorithm>
using namespace std;//[]
const int maxn = 100010;
int tree[20][maxn];//每层每个位置的值
int sorted[maxn];//排好序的数组,方便寻找中值
int leftsum[20][maxn];//有多少个数分到该层该位置左边
void build(int p, int l, int r)
{
if(l == r) return;
int mid = (l + r)/2;
int same = mid - l + 1;
int x = sorted[mid];
for(int i = l; i <= r; i++){
if(tree[p][i] < x) same--;
}//与中值相等的数填满区间一半
int tl = l, tr = mid + 1;
for(int i = l; i <= r; i++){
if(tree[p][i] < x)
tree[p + 1][tl++] = tree[p][i];
else if(tree[p][i] == x && same>0){
tree[p + 1][tl++] = tree[p][i];
same--;
}else
tree[p + 1][tr++] = tree[p][i];
leftsum[p][i] = leftsum[p][l-1] + tl - l;
}
build(p + 1, l, mid);
build(p + 1, mid + 1, r);
}
//[L,R]中的[l,r]的第k大数
int query(int L, int R, int l, int r, int p, int k)
{
if(l == r) return tree[p][l];
int mid = (L + R)/2;
int cnt = leftsum[p][r] - leftsum[p][l-1];
if(cnt >= k){
int newl = L + leftsum[p][l-1] - leftsum[p][L-1];
int newr = newl + cnt - 1;
return query(L, mid, newl, newr, p+1, k);
}else {
int newr = r + leftsum[p][R] - leftsum[p][r];
int newl = newr - (r - l - cnt);
return query(mid+1, R, newl, newr, p+1, k - cnt);
}
}
int main (void)
{
int n, m;scanf("%d%d",&n,&m);
for(int i = 1; i <=n; i++){//下标从1开始
scanf("%d",&tree[0][i]);
sorted[i] = tree[0][i];
}
sort(sorted+1, sorted+n+1);
build(0, 1,n);
int s, t, k;
while(m--){
scanf("%d%d%d",&s,&t,&k);
printf("%d\n",query(1, n, s, t, 0, k));
}
return 0;
}

划分树还是挺好理解的,接下来看看归并树和主席树。

静态区间第k大(划分树)的更多相关文章

  1. poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 43315   Accepted: 14296 Ca ...

  2. 静态区间第k大(归并树)

    POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...

  3. 主席树(静态区间第k大)

    前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...

  4. 可持久化线段树(主席树)——静态区间第k大

    主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...

  5. HDU3473--Minimum Sum(静态区间第k大)

    Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  6. POJ 2104 && POJ 2761 (静态区间第k大,主席树)

    查询区间第K大,而且没有修改. 使用划分树是可以做的. 作为主席树的入门题,感觉太神奇了,Orz /* *********************************************** ...

  7. 静态区间第k大(主席树)

    POJ 2104为例(主席树入门题) 思想: 可持久化线段树,也叫作函数式线段树,也叫主席树(高大上). 可持久化数据结构(Persistent data structure):利用函数式编程的思想使 ...

  8. 主席树学习笔记(静态区间第k大)

    题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...

  9. POJ2104-- K-th Number(主席树静态区间第k大)

    [转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249 无修改的区间第K大 我们先考虑简化的问题:我们要询问整个区间内的第K大.这样我们对值域建线段 ...

  10. HDU 2665 Kth number(主席树静态区间第K大)题解

    题意:问你区间第k大是谁 思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的. 具体可以看q学姐的B站视频 代码: #include<cmath> #i ...

随机推荐

  1. 实现通知栏Notification

    课程Demo public class MainActivity extends Activity implements OnClickListener{ NotificationManager ma ...

  2. 临时笔记 Protection

    如果操作系统不使用处理器的多任务机制,它仍然需要为栈创建至少一个TSS 当程序通过调用门改变特权级的时候,处理器执行下面的步骤切换栈,并且执行被调用的程序在新的特权级 1. 使用目标代码段的DPL从T ...

  3. asp.net C# 获得配置文件AppSettings 的值

    using System.Configuration;//导入命名空间 //配置文件 Web.config <appSettings> <!--数据连接字符串--> <a ...

  4. LeetCode1-5

    Leetcode1: Given an array of integers, return indices of the two numbers such that they add up to a ...

  5. js小结(一)

    想要的效果:比如说返回 25%  12.5% 33.33% 有几位小数就显示几位,就用 a=Math.round(a*100)/100 如果想要强制返还两位小数,就使用 a=a.toFixed(2); ...

  6. CSS Paint API绘制透明格子背景实例页面

    CSS代码: .box { width: 180px; height: 180px; background: paint(transparent-grid); } HTML代码: <div cl ...

  7. enote笔记法的思考(ver0.2)

    章节:enote笔记法的思考   enote笔记法,它是一种独特的文本标记方式与呈现方式.这一整套系统的记笔记的方法,它能够帮助我们对文本内容(例如,其中的概念.观点.思想等)更加直观和条理地进行理性 ...

  8. HDU - 2612 Find a way(BFS搜索)

    题目: 链接 思路: 用BFS分别以‘Y’和‘M’的位置为起点进行两次搜索,并把这两次的搜索结果在一个二维数组中保存下来,在对地图遍历遇到‘@’更行最小值. PS: 如果用‘Y’和‘M’点分别去搜每个 ...

  9. google查找笔记

    1.可以选择MDN.WIKI等权威的网址资料

  10. redis 的安装及常用的命令

    前言: redis是一个key-value的存储系统,value支持string.list.set.zset.hash五种类型,且支持数据的本地存储 一.安装redis 前提:linux下需要安装了m ...