K-th Number POJ - 2104

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. 

Input

The 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

For each question output the answer to it --- the k-th number in sorted a[i...j] segment. 

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

This problem has huge input,so please use c-style input(scanf,printf),or you may got time limit exceed.
 
 
题意:求区间第k大
题解:主席树的板子
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<cmath>
#include<stack>
#include<cstdlib>
#include <vector>
#include<queue>
using namespace std; #define ll long long
#define llu unsigned long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
const int maxn = 1e5+;
const int mod = 1e9+; int n,q,m,tot;
int a[maxn],t[maxn],T[maxn],lson[maxn*],rson[maxn*],c[maxn*]; void Init_hash()
{
for(int i=;i<=n;i++)
t[i] = a[i];
sort(t+,t++n);
m = unique(t+,t++n)-t-;
} int build(int l,int r)
{
int root = tot++;
c[root] = ;
if (l != r)
{
int mid = (l+r) >> ;
lson[root] = build(l,mid);
rson[root] = build(mid+,r);
}
return root;
}
int Hash(int x)
{
return lower_bound(t+,t++m,x)-t;
}
int update(int root,int pos,int val)
{
int newroot = tot ++,tmp = newroot;
c[newroot] = c[root] + val;
int l = ,r = m;
while(l <r)
{
int mid = (l+r)>>;
if(pos <= mid)
{
lson[newroot] = tot++;
rson[newroot] = rson[root];
newroot = lson[newroot];
root = lson[root];
r = mid;
}
else
{
rson[newroot] = tot ++;
lson[newroot] = lson[root];
newroot = rson[newroot];
root = rson[root];
l = mid + ;
}
c[newroot] = c[root] + val;
}
return tmp; }
int query(int left_root,int right_root,int k)
{
int l = ,r = m;
while(l < r)
{
int mid = (l+r) >> ;
if(c[lson[left_root]] - c[lson[right_root]] >= k)
{
r = mid;
left_root = lson[left_root];
right_root = lson[right_root];
}
else
{
l = mid + ;
k -= c[lson[left_root]] - c[lson[right_root]];
left_root = rson[left_root];
right_root = rson[right_root];
}
}
return l;
}
int main()
{
scanf("%d%d",&n,&q);
tot = ;
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
Init_hash();
T[n+] = build(,m);
for(int i=n;i;i--)
{
int pos = Hash(a[i]);
T[i] = update(T[i+],pos,);
}
while(q--)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",t[query(T[l],T[r+],k)]);
}
}
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<stack>
#include<cstdlib>
#include<queue>
#include<set>
#include<string.h>
#include<vector>
#include<deque>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define eps 1e-4
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
typedef long long LL;
typedef long long ll;
const int maxn = 2e5 + ;
const int mod = ;
int n,m,a[maxn],root[maxn],cnt;
vector<int>v;
struct node{
int l,r,sum;
}T[maxn * ];
int getid(int x) {
return lower_bound(v.begin(),v.end(),x) - v.begin() + ;
}
void update(int l,int r,int &x,int y,int pos) {
T[++cnt] = T[y],T[cnt].sum ++,x = cnt;
if(l == r) return;
int mid = (l + r) / ;
if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos);
else update(mid + ,r,T[x].r,T[y].r,pos);
}
int query(int l,int r,int x,int y,int k) {
if(l == r) return l;
int mid = (l + r) / ;
int sum = T[T[y].l].sum - T[T[x].l].sum;
if(sum >= k) return query(l,mid,T[x].l,T[y].l,k);
else return query(mid + ,r,T[x].r,T[y].r,k - sum);
}
void init() {
cnt = ;
memset(root,,sizeof root);
}
int main()
{
init();
scanf("%d %d",&n,&m);
for (int i = ; i <= n; ++i) {
scanf("%d",&a[i]);
v.push_back(a[i]);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for (int i = ; i <= n; ++i)
update(,n,root[i],root[i - ],getid(a[i]));
for (int i = ; i <= m; ++i) {
int x,y,k;
scanf("%d %d %d",&x, &y, &k);
printf("%d\n",v[query(,n,root[x - ],root[y],k) - ]);
}
}
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<stack>
#include<cstdlib>
#include<queue>
#include<set>
#include<string.h>
#include<vector>
#include<deque>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define eps 1e-4
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl
typedef long long LL;
typedef long long ll;
const int maxn = 2e5 + ;
const int mod = ;
int n,m,a[maxn],root[maxn],cnt;
/*
root:代表每个历史版本线段树的根节点位置
cnt:用作开辟新的树节点
*/
vector<int>v;
struct node{
int l,r,sum;
}T[maxn * ]; //线段树区间统计,sum代表在这个区间数的个数
int getid(int x) { //获取离散数组后的下标
return lower_bound(v.begin(),v.end(),x) - v.begin() + ;
}
/*
update函数:
y代表前一棵树的节点位置,x是后面的节点位置
*/
void update(int l,int r,int &x,int y,int pos) {
//&x 引用节点指针扩展新节点
T[++cnt] = T[y],T[cnt].sum ++,x = cnt; //新开节点,将需要修改的树节点复制到新开辟节点,改变自己的sum
if(l == r) return;
int mid = (l + r) / ;
if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos); //节点左边
else update(mid + ,r,T[x].r,T[y].r,pos); //节点右边
}
int query(int l,int r,int x,int y,int k) {
if(l == r) return l;
int mid = (l + r) / ;
int sum = T[T[y].l].sum - T[T[x].l].sum; //两颗线段树sum做差
if(sum >= k) return query(l,mid,T[x].l,T[y].l,k); //如果当前的结点个数sum比k要大的话,说明第k大的结点在左子树当中,就去遍历左子树
else return query(mid + ,r,T[x].r,T[y].r,k - sum); //如果当前的结点个数sum比k要小的话,说明第k大的结点在右子树当中,而左子树的结点个数是sum个,那就去找右子树中的第k-sum的数
}
void init() {
cnt = ;
memset(root,,sizeof root);
}
int main()
{
init();
scanf("%d %d",&n,&m);
for (int i = ; i <= n; ++i) {
scanf("%d",&a[i]);
v.push_back(a[i]); //离散化数组
}
sort(v.begin(),v.end()); //离散化数组
v.erase(unique(v.begin(),v.end()),v.end()); //离散化数组 for (int i = ; i <= n; ++i) {
update(, n, root[i], root[i - ], getid(a[i]));
}
for (int i = ; i <= m; ++i) {
int x,y,k;
scanf("%d %d %d",&x, &y, &k);
printf("%d\n",v[query(,n,root[x - ],root[y],k) - ]);
}
}

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

  1. K-th Number Poj - 2104 主席树

    K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...

  2. 主席树 【权值线段树】 && 例题K-th Number POJ - 2104

    一.主席树与权值线段树区别 主席树是由许多权值线段树构成,单独的权值线段树只能解决寻找整个区间第k大/小值问题(什么叫整个区间,比如你对区间[1,8]建立一颗对应权值线段树,那么你不能询问区间[2,5 ...

  3. K-th Number POJ - 2104 划分树

    K-th Number You are working for Macrohard company in data structures department. After failing your ...

  4. HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. AC日记——K-th Number poj 2104

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

  6. hdu 2665 Kth number (poj 2104 K-th Number) 划分树

    划分树的基本功能是,对一个给定的数组,求区间[l,r]内的第k大(小)数. 划分树的基本思想是分治,每次查询复杂度为O(log(n)),n是数组规模. 具体原理见http://baike.baidu. ...

  7. POJ 2104&HDU 2665 Kth number(主席树入门+离散化)

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

  8. poj 2104 K-th Number 主席树+超级详细解释

    poj 2104 K-th Number 主席树+超级详细解释 传送门:K-th Number 题目大意:给出一段数列,让你求[L,R]区间内第几大的数字! 在这里先介绍一下主席树! 如果想了解什么是 ...

  9. poj 2104 K-th Number(主席树,详细有用)

    poj 2104 K-th Number(主席树) 主席树就是持久化的线段树,添加的时候,每更新了一个节点的线段树都被保存下来了. 查询区间[L,R]操作的时候,只需要用第R棵树减去第L-1棵树就是区 ...

随机推荐

  1. Oracle 搭建Node.js开发环境

      先决条件 安装oralce客户端驱动. 安装node.js.   创建项目 安装oracledb模块 $npm install oracledb 如果失败了,你可能要爬墙.   参考package ...

  2. C#简单代码转移数据库数据

    using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Data;u ...

  3. CI框架更新与删除

    $this->load->database();        // $query=$this->db->get('t_repayments');        // $res ...

  4. 封装一个帮助类来写文件到android外置存储器上

    项目地址:点击打开 项目简介:写文件到android外置存储器的一个帮助类,和它的demo程序 它是如何工作的呢? 1.创建 AppExternalFileWriter 对象并传递context(上下 ...

  5. 7天学完Java基础之0/7

    笔记-7天学完Java基础之0/7 1.常用命令提示符(cmd) 启动:Win+R,输入cmd​

  6. VS功能扩展--扩展介绍

    使用Eclipse的朋友都知道Eclipse是一个完全可扩展的IDE,那么在windows程序开发时,我们常使用的IDE(Visual studio)是否具有功能的扩展性呢?毫无疑问,回答是肯定的.我 ...

  7. webapplication发布

    在vs2010里写的 ASP.NET Web Application 发布步骤: ①:右击Web Application项目可以看到发布,弹出的对话框里选择要发布的路径,路径选择一个容易记住的地址即可 ...

  8. Python3基础12(collections、struct、itertools、chardet等的使用)

    import struct import base64import itertoolsimport chardet from collections import namedtuple,default ...

  9. IOS 监听slider滑动

    // 监听slider滑动 - (IBAction)valueChnage:(UISlider *)sender; @property (weak, nonatomic) IBOutlet NJVie ...

  10. pyqt4 python2.7 中文乱码的解决方法

    import sysimport localefrom PyQt4.QtGui import *from PyQt4.QtCore import *from untitled import Ui_Di ...