【POJ2104】【HDU2665】K-th Number

Description

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.
题意:n个数,m次询问,每次求区间[l,r]中的第k小的数
题解:主席树模板(什么是主席树?)
主席树也叫可持久化线段树、函数式线段树,我感觉就跟动态开点线段树差不多(什么是动态开点线段树?)
正常的线段树就是lson=x<<1,rson=x<<1|1,但动态开点线段树不同,它的节点的左右儿子是即用即开的,并用数组记录,每搜到一个点,如果以前没开过,就新开一个点,然后继续搜。这样我们就可以将多个线段树放到一起(怎么做?)
如果许多互部重叠线段树都建在[1,n]这个区间上,那么我们就可以直接将他们都放到一起,分别记录每棵线段树的根root[i],然后正常的在线段树上搞,当需要用到一段没开过的区间时,就新开一个点记录这个区间,然后继续向下查询,如果需要就在开新的点。这样我们可以对每棵线段树进行操作,空间复杂度O(nlogn)
好了,下面说主席树,主席树当然也要动态开点,建n棵线段树(都是权值线段树),不过第i棵线段树保存的是[1,i]这段区间,也就相当于一个前缀(那空间复杂度岂不是O(n^2)?)
于是我们发现,这一堆线段树其实有很大一部分是重复的,比如第i棵线段树,它相当于第i-1棵线段树中新开了一个点a[i],那么如果a[i]在[1,mid]这段区间里,那么第i棵线段树和第i-1课线段树的[mid+1,r]这段区间就是完全相同的!于是我们直接让他们共用这段区间即可(方法:把root[i]的右儿子指针指到root[i-1]的右儿子上,仅新建一个root[i]的左儿子)。同理,如果a[i]在[mid+1,r]这段区间里,我们就让他们共用左儿子,然后继续这样做,直到l==r。于是空间复杂度:O(nlogn)
那查询的时候该怎么做呢,对于本题,[l,r]中的第k小,那么我们已经处理出了[1,r]和[1,l-1]这两棵线段树,那么我们将这两棵线段树相减(因为是权值线段树,所以将每个点都相减即可),就相当于得到了一棵新的线段树[l,r],然后再求整体的第k小(这就很简单了吧)
上面说的这些也不算详解吧,其实就是我个人对主席树的一些理解罢了。
注意:可能有负数
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=100010;
struct node
{
int ls,rs,siz;
}s[4000010];
struct NUM
{
int num,org;
}v[maxn];
int n,m,tot,nm;
int root[maxn],ref[maxn];
bool cmp1(NUM a,NUM b)
{
return a.num<b.num;
}
bool cmp2(NUM a,NUM b)
{
return a.org<b.org;
}
int readin()
{
int ret=0,f=1; char gc;
while(gc<'0'||gc>'9') {if(gc=='-')f=-f;gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void pushup(int x)
{
s[x].siz=s[s[x].ls].siz+s[s[x].rs].siz;
}
void insert(int &x,int &y,int l,int r,int p)
{
y=++tot;
if(l==r)
{
s[y].siz=s[x].siz+1;
return ;
}
int mid=l+r>>1;
if(p<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,p);
else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,p);
pushup(y);
}
int query(int x,int y,int l,int r,int p)
{
if(l==r) return ref[l];
int mid=l+r>>1;
if(s[s[y].ls].siz-s[s[x].ls].siz>=p) return query(s[x].ls,s[y].ls,l,mid,p);
return query(s[x].rs,s[y].rs,mid+1,r,p-s[s[y].ls].siz+s[s[x].ls].siz);
}
int main()
{
n=readin(),m=readin();
int i,a,b,c;
for(i=1;i<=n;i++) v[i].num=readin(),v[i].org=i;
sort(v+1,v+n+1,cmp1);
ref[0]=-1<<30;
for(i=1;i<=n;i++)
{
if(v[i].num>ref[nm]) ref[++nm]=v[i].num;
v[i].num=nm;
}
sort(v+1,v+n+1,cmp2);
for(i=1;i<=n;i++)
insert(root[i-1],root[i],1,nm,v[i].num);
for(i=1;i<=m;i++)
{
a=readin(),b=readin(),c=readin();
printf("%d\n",query(root[a-1],root[b],1,nm,c));
}
return 0;
}

【POJ2104】【HDU2665】K-th Number 主席树的更多相关文章

  1. poj2104 k-th number 主席树入门讲解

    poj2104 k-th number 主席树入门讲解 定义:主席树是一种可持久化的线段树 又叫函数式线段树   刚开始学是不是觉得很蒙逼啊 其实我也是 主席树说简单了 就是 保留你每一步操作完成之后 ...

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

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

  3. poj2104 K-th Number区间第k小值 主席树

    原来主席树就是可持久化线段树啊,刚知道,,, 作为一道裸题,还是必A的,然而一开始偷懒不写离散化跪了N多遍,后来在缪大的帮助下发现了这个问题,遂A之 ——又是这种破问题,实在不想说自己了 把n个数看成 ...

  4. POJ2104 K-th Number[主席树]【学习笔记】

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

  5. [poj2104] K-th Number (主席树)

    主席树 Description You are working for Macrohard company in data structures department. After failing y ...

  6. 主席树:POJ2104 K-th Number (主席树模板题)

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

  7. POJ 2104 K-th Number 主席树(区间第k大)

    题目链接: http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MSMemory Limit: 65536K 问题描述 You ar ...

  8. 【poj2104】K-th Number 主席树

    题目描述 You are working for Macrohard company in data structures department. After failing your previou ...

  9. POJ 2104 K-th Number ( 求取区间 K 大值 || 主席树 || 离线线段树)

    题意 : 给出一个含有 N 个数的序列,然后有 M 次问询,每次问询包含 ( L, R, K ) 要求你给出 L 到 R 这个区间的第 K 大是几 分析 : 求取区间 K 大值是个经典的问题,可以使用 ...

随机推荐

  1. HDU 2802 F(N) 数论+打表

    题目大意:f[n]-n^3=f[n-2]-(n-1)^3 (n >=3),f[1]=1,f[2]=7,求f[n]. 题目思路:将n^3移到到等式右边化简的到:f[n]=f[n-2]+3n*(n- ...

  2. VIM继承C语言(转)

    在下面的基础上加上了astyle sh.c --style=kr --indent=spaces --indent-cases --pad-header --pad-oper --unpad-pare ...

  3. php下载文件的一种方式

    <?php ob_start(); // $file_name="cookie.jpg"; $file_name="abc.jpg"; //用以解决中文不 ...

  4. ant脚本

    jenkins在调用ant脚本时会遇到ant中的目标没有成功,但是最后的build状态却是success,如下图所示:代码中缺少一个},编译发生错误,最后的build成功. 解决方案:在关键的targ ...

  5. ajax2016/4/15 post与get

    post方式,数据放在send()里面作为参数传递 xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); ...

  6. Git学习 -- 分支管理

    创建新分支,并切换到该分支 git checkout -b dev 这一句相当于以下两句: git branch dev 创建 git checkout dev 切换 查看当前分支 git branc ...

  7. Git 分支-利用分支进行开发的工作流程

    3.4 Git 分支 - 利用分支进行开发的工作流程 利用分支进行开发的工作流程 现在我们已经学会了新建分支和合并分支,可以(或应该)用它来做点什么呢?在本节,我们会介绍一些利用分支进行开发的工作流程 ...

  8. ratingbar设置不可调节星星数量

    <RatingBar android:id="@+id/rb_bar" android:layout_width="wrap_content" andro ...

  9. 以前的loginUI

    的 <%@ page language="java" pageEncoding="UTF-8"%> <%@ include file=&quo ...

  10. 表达式语言--在MVC中应用表达式语言

    之前讲解的MVC设计模式中一直有DAO存在,而且所有的对象都保存在VO之中,那么这时如果将一个VO传递到JSP文件中,那么JSP需要导入VO包,如果使用表达式语言的话,导入VO包就没有任何意义了. V ...