You are working for Macrohard company in data structures department. After failing your previous task about key insertion you were asked to write a new data structure that would be able to return quickly k-th order statistics in the array segment. 
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?" 
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.

(主席树求区间第k小)

——by POJ;

http://poj.org/problem?id=2104



先%hjt吧;

主席树静态求区间第K小;

先对数据按大小离散化;

然后明确两个概念:

  • 排名区间:排名区间[l,r]表示要维护排名在lr间的数据的相关信息;
  • 原序列区间:原序列区间[x,y]表示要维护在原序列(至把数据按读入的顺序排列的序列)中xy间的数据的相关信息;

我们对原序列中的每一个点,维护她的前缀信息——

信息是:一棵线段树——以排名区间为区间,维护有多少数据在该区间里(如原序列:3,3,2,1,3,则第3位的前缀是{3,3,2},于是维护{3,3,2}中有几个在排名区间[1,3]中,有几个在排名区间[1,2],有几个在排名区间[3,3]...);

这样你得到了如下信息:

  • 原序列区间[1,j]中数据在排名区间中的分布(因为你记录了前缀影响下的线段树嘛);
  • 利用上一条信息得出:原序列区间[i,j]中数据在排名区间中的分布(对前缀进行差分);

在我们有原序列区间[i,j]中数据在排名区间中的分布信息后,

  若排名区间[l,mid]中分布k+个数据,则区间[l,r]的第k小必然在该区间里;

  否则在排名区间[mid+1,r]中;

  然后在线段树上递归分治即可;

以上是中心思路——

然后,是一些要点:

  如,如何N棵线段树的内存问题?

    其实,表面上看我们要开N棵树,但是相邻两树只有受一个数据影响而产生的差距——这只会造成一条树链的不同;

  这样只存一棵树和N-1条链即可;

  习惯上我们一般以完全二叉树的方式存储,在这里是不行的;

  用最朴素的二叉树存储方法,即对一个点,维护她所代表的区间的信息和左右子节点的下标信息即可;

  然后可以考虑内存池模拟系统内存分配的方法(我一开始还以为是内存尺的说);

(终于把这篇拖了许久的东西发上来了,大概是我写的最长的随笔了吧;)

代码如下:

 #include<cstdio>
#include<algorithm>
using namespace std;
struct ss
{
int size,num;
}a[];
int b[],fa[],L,R,K,now;
struct tre
{
int l,r,num;
}tr_data[];
int tot; bool cmp1(ss a,ss b)
{ return a.size<b.size; } bool cmp2(ss a,ss b)
{ return a.num<b.num; }
void build(int ,int ,int ,int );
void work(int ,int ,int ,int ); int main()
{
int i,j=,k;
int n,m;
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)
scanf("%d",&a[i].size),a[i].num=i; sort(a+,a+n+,cmp1);
for(i=;i<=n;i++)
{
if(a[i].size!=a[i-].size)++j;
b[j]=a[i].size;
a[i].size=j; }
sort(a+,a+n+,cmp2); for(i=;i<=n;i++)
{
fa[i]=++tot;
now=a[i].size;
build(,j,tot,fa[i-]);//////
}
for(i=;i<=m;i++)
{
scanf("%d%d%d",&L,&R,&K);
work(,j,fa[R],fa[L-]);//////
}
return ;
} void build(int l,int r,int nu,int pre)
{
if(l==r)
{
tr_data[nu].num=tr_data[pre].num+;
return;
}
int mid=(l+r)>>;
if(now<=mid)
{
tr_data[nu].l=++tot;
build(l,mid,tr_data[nu].l,tr_data[pre].l);
tr_data[nu].r=tr_data[pre].r;
}
else
{
tr_data[nu].r=++tot;
build(mid+,r,tr_data[nu].r,tr_data[pre].r);
tr_data[nu].l=tr_data[pre].l;
}
tr_data[nu].num=tr_data[tr_data[nu].l].num+tr_data[tr_data[nu].r].num;
} void work(int l,int r,int now,int pre)
{
if(l==r)
{
printf("%d\n",b[l]);
return ;
}
int mid=(l+r)>>;
if(tr_data[tr_data[now].l].num-tr_data[tr_data[pre].l].num>=K)
work(l,mid,tr_data[now].l,tr_data[pre].l);
else
{ K=K-(tr_data[tr_data[now].l].num-tr_data[tr_data[pre].l].num);
work(mid+,r,tr_data[now].r,tr_data[pre].r); }
}

祝AC哟;

POJ P2104 K-th Number的更多相关文章

  1. POJ 3111 K Best(01分数规划)

    K Best Time Limit: 8000MS   Memory Limit: 65536K Total Submissions: 9876   Accepted: 2535 Case Time ...

  2. poj 3111 K Best (二分搜索之最大化平均值之01分数规划)

    Description Demy has n jewels. Each of her jewels has some value vi and weight wi. Since her husband ...

  3. poj 3111 K Best 最大化平均值 二分思想

    poj 3111 K Best 最大化平均值 二分思想 题目链接: http://poj.org/problem?id=3111 思路: 挑战程序竞赛书上讲的很好,下面的解释也基本来源于此书 设定条件 ...

  4. POJ - 3111 K Best 0-1分数规划 二分

    K Best Time Limit: 8000MS   Memory Limit: 65536K Total Submissions: 12812   Accepted: 3290 Case Time ...

  5. 【POJ】2104 K-th Number(区间k大+主席树)

    http://poj.org/problem?id=2104 裸题不说.主席树水过. #include <cstdio> #include <iostream> #includ ...

  6. POJ 2104:K-th Number(主席树静态区间k大)

    题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var ...

  7. POJ 2699 The Maximum Number of Strong Kings Description

    The Maximum Number of Strong Kings   Description A tournament can be represented by a complete graph ...

  8. POJ 3111 K Best(二分答案)

    [题目链接] http://poj.org/problem?id=3111 [题目大意] 选取k个物品,最大化sum(ai)/sum(bi) [题解] 如果答案是x,那么有sigma(a)>=s ...

  9. POJ 2104:K-th Number(整体二分)

    http://poj.org/problem?id=2104 题意:给出n个数和m个询问求区间第K小. 思路:以前用主席树做过,这次学整体二分来做.整体二分在yr大佬的指点下,终于大概懂了点了.对于二 ...

随机推荐

  1. 题目1003:A+B(字符串转数字)

    问题来源 http://ac.jobdu.com/problem.php?pid=1003 问题描述 每次给你两个数,数的形式是每三位有一个间隔符',',计算两数之和. 问题分析 两个问题,一.如何读 ...

  2. @ModelAttribute注解和POJO传参过程

    1.@ModelAttribute注解 @ModelAttribute主要有三个用途,对方法进行注解,对参数进行注解,还有@ModelAttribute和@RequestMapping一起对方法进行注 ...

  3. QuantLib 金融计算——基本组件之 InterestRate 类

    目录 QuantLib 金融计算--基本组件之 InterestRate 类 InterestRate 对象的构造 一些常用的成员函数 如果未做特别说明,文中的程序都是 Python3 代码. Qua ...

  4. Java中静态变量的声明位置

    Java中静态变量只能是成员变量,局部方法中的局部变量除final外不能有任何其他修饰符,例如: public class Test { static String x = "1" ...

  5. Axis2 Web Service Development & Deployment Guide(Axis2使用)

    主要内容: 记录关于Axis2的使用,通过WSDL文件生成Web service的客户端和服务器端的过程. 目录: Requirement(必备工具) Development - Client Gen ...

  6. docker仓库harbor镜像列表获取命令

    2019-03-14 搭建好docker仓库harbor之后,在服务器上获取harbor的所有镜像列表命令 curl -u "harbor账号:密码" -X GET -H &quo ...

  7. C#方法重载和方法重写的区别

    一.重载的条件: 1.必须在同一个类中: 2.方法名必须相同: 3.参数列表不能相同. 二.重写的条件: 1. 在不同的类中2. 发生方法重写的两个方法返回值,方法名,参数列表必须完全一致(必须具有相 ...

  8. (转)mysql 备份与恢复mysqlhotcopy

    原文:http://fuwenchao.blog.51cto.com/6008712/1331910 mysqlhotcopy是一个Perl脚本,最初由Tim Bunce编写并提供.它使用LOCK T ...

  9. vSphere虚拟主机安装Centos7系统

    经过上一帖的主机设置,这一步就可以开始安装系统了,本次详细记录各个过程并分析结果. Centos7 1.右键点击列表中的虚拟主机,打开控制台. 点击绿色开机键,开始安装. 这里有一个很关键的点,就是上 ...

  10. List的定制排序 包括使用lambda表达式来实现的方法

    1.先实现Comparator的接口 重写compare方法 根据比较大小来返回数值: 比如:(Integer o1  -   Integer o2); return 1 表示o1>o2; re ...