POJ2104 K-th Number (子区间内第k大的数字)【划分树算法模板应用】
Time Limit: 20000MS | Memory Limit: 65536K | |
Total Submissions: 40920 | Accepted: 13367 | |
Case Time Limit: 2000MS |
Description
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.
Input
first line of the input file contains n --- the size of the array, and m
--- the number of questions to answer (1 <= n <= 100 000, 1 <=
m <= 5 000).
The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given.
The following m lines contain question descriptions, each
description consists of three numbers: i, j, and k (1 <= i <= j
<= n, 1 <= k <= j - i + 1) and represents the question Q(i, j,
k).
Output
Sample Input
7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
Sample Output
5
6
3
Hint
算法及题目分析:给你一个具有n个数字的数组,进行m此询问。每次询问,都会给你一个子区间,问你这个区间内的第k大的数字是多少?例如:数组序列(下标从1开始)是:1 5 2 6 3 7 4, 询问:[2, 5]的第3大的数字。[2, 5]区间的数是:5 2 6 3,排序后:2 3 5 6,第3大的数应该是5. 但是当数据量比较庞大的时候,询问次数比较多的时候,这种常规算法思想实现起来之星效率比较低。于是一种树型结构算法应运而生:【划分树算法】(基于线段树思想)(划分树实现细节有待补充)。【可以参考:程序设计 解题策略 吴永辉 王建德 编著 P2】
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
#define N 100000+10 using namespace std; //POJ 2104
int tree[50][N];//tree[p][i]表示第p层中第i的位置的值
int sorted[N];
int toleft[50][N];//toleft[p][i]表示第p层从1到i中有
//多少个数被划分入下一层的左子区间 //划分树建树的实现过程
void build(int ll ,int r, int dep)
{
if(ll==r)
return; //递归出口 若划分至叶子,则回溯
int mid=(ll+r)>>1; //等于(l+r)/2 计算区间的中间指针
int same=mid-ll+1; //计算[l,r]被分入下层左区间的个数
for(int i=ll; i<=r; i++)
{
if(tree[dep][i] < sorted[mid])
same--;
}
int llpos=ll;
int rpos=mid+1;
for(int i=ll; i<=r; i++)
{
if(tree[dep][i] < sorted[mid])
tree[dep+1][llpos++]=tree[dep][i];
else if(tree[dep][i]==sorted[mid] && same>0 )
{
tree[dep+1][llpos++]=tree[dep][i];
same--;
}
else
tree[dep+1][rpos++]=tree[dep][i];
toleft[dep][i]=toleft[dep][ll-1] +llpos-ll;
}
build(ll, mid, dep+1);//递归计算下一层的左子区间
build(mid+1, r, dep+1);//递归计算下一层的右子区间
} int query(int L, int R, int ll, int r, int dep, int k)
//从划分数的dep层出发 自上而下的在大区间[L,R]里查询子区间
//[ll,r]中第K大的数
{
if(ll==r)
return tree[dep][ll];
int mid=(L+R)>>1;
int cnt=toleft[dep][r]-toleft[dep][ll-1];
if(cnt >= k)
{
int newll=L+toleft[dep][ll-1]-toleft[dep][L-1];
int newr = newll+cnt-1;
return query(L, mid, newll, newr, dep+1, k);
}
else
{
int newr=r+toleft[dep][R]-toleft[dep][r];
int newll=newr-(r-ll-cnt);
return query(mid+1, R, newll, newr, dep+1, k-cnt);
}
} int main()
{
int n, m;
int i; while(~scanf("%d %d", &n, &m))
{
for(i=1; i<=n; i++)//n
{
scanf("%d", &tree[0][i]);//
sorted[i]=tree[0][i];
}
sort(sorted+1,sorted+n+1);
build(1, n, 0);//建立划分树
while(m--)
{
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
printf("%d\n", query(1, n, u, v, 0, w));
}
}
return 0;
}
POJ2104 K-th Number (子区间内第k大的数字)【划分树算法模板应用】的更多相关文章
- 【大杀器】利用划分树秒杀区间内第k大的数
最近看了一道题,大概就是给出一个序列,不断询问其子区间内第k大的数,下面是个截图 绕了一圈没找到中文版题目,if(你是大佬) then 去看截图:else{我来解释:给出一个整数n,和一个整数m,分别 ...
- POJ2104 K-th Number —— 静态区间第k小
题目链接:http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Sub ...
- 序列内第k小查询(线段树)
最近请教了一下大佬怎么求序列内第k大查询,自己又捣鼓了一下,虽然还没有懂得区间第k大查询,不过姑且做一个记录先吧 因为每个元素大小可能很大而元素之间不连续,所以我们先离散化处理一下,程序中的ori[ ...
- [LeetCode] Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K
Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...
- [LeetCode] Kth Largest Element in an Array 数组中第k大的数字
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- 【POJ2104】K-th Number
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABToAAAJ2CAIAAADwi6oDAAAgAElEQVR4nOy9a5Pj1nnvi0/Q71Llj3
- C++之路进阶——poj2104(K-th Number)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 44537 Accepted: 14781 Ca ...
- LeetCode 560. Subarray Sum Equals K (子数组之和等于K)
Given an array of integers and an integer k, you need to find the total number of continuous subarra ...
- 【poj2104】K-th Number 主席树
题目描述 You are working for Macrohard company in data structures department. After failing your previou ...
随机推荐
- EasyUI+zTree实现简单的树形菜单切换
使用easyui_ztree实现简单的树形菜单切换效果 <!DOCTYPE html> <html> <head> <meta charset="U ...
- C 语言实例
C 语言实例 C 语言实例 - 输出 "Hello, World!" C 语言实例 - 输出整数 C 语言实例 - 两个数字相加 C 语言实例 - 两个浮点数相乘 C 语言实例 - ...
- 对于Json和对象转换的学习
学习这个的用处有非常多的: 在传输数据过程中比較查看数据比較清晰,代码也较清晰.也能够避免split函数带来的隐藏bug 当然也有不足: 准备工具较繁琐,须要准备对象(当然 ...
- HTTP头解读
Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET.POST.PUT.DELETE.一个URL地址用于描述一个网络上的资源, 而HTTP中的GET.POST.PUT. DELETE ...
- iTunes备份注意
记住: 如果你有重要的信息在iTunes中无备份的话.那么开始不要同步了. 退出时,最好备份后在退出.
- jquery插件函数传参错误
1.jquery传参通过json,可能的错误是,参数中的结束符写成了;
- 仿VS安装界面小球滑动效果
在Visual Studio 2010后续版本的安装界面中,可以发现一组小球在滑动表示安装程序正在进行: 于是尝试用CSS实现了一下. 首先需要建立用来表示小球的html结构: <div cla ...
- Newtonsoft.Json读取txt文件中json数据并存到SQL service 数据库!
using System; using System.Collections.Generic; using System.Text; using System.IO; using Newtonsoft ...
- php 字符串内容是数组格式 转换成数组
一个简单的应用.. 例, $str = "array( 'USD'=>'1', 'GBP'=>'0.6494', 'EUR'=>'0.7668' ,'JPY'= ...
- 关于proplists:get_value/2 与lists:keyfind/3 的效率比较
关于proplists:get_value/2 与lists:keyfind/2 的效率 早有比较,已出结论,lists:keyfind/2 的效率要好很多,好些人都是直接用或者做过它们之间的比较测试 ...