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. JSP标签和JSTL标签注意点

    1.转发和重定向问题 当前项目:/Test 转发路径:"/"根目录表示当前项目"/Test","/login.jsp"就是"/Te ...

  2. SpringBoot | 第二章:lombok介绍及简单使用

    在去北京培训的时候,讲师说到了lombok这个第三方插件包,使用了之后发现,确实是个神奇,避免了编写很多臃肿的且定式的代码,虽然现代的IDE都能通过快捷键或者右键的方式,使用Generate Gett ...

  3. 服务器部署nginx报错 nginx: [warn] conflicting server name "localhost" on xxx.xxx.xxx.xxx:80, ignored

    问题 修改nginx配置参数后,使用nginx -t检查配置. 提示successfull后就可以使用 nginx -s reload来重新加载配置 我配置的过程中遇到这样的问题,就是绑定了主机名后, ...

  4. spring的工厂方法

    http://blog.csdn.net/nvd11/article/details/51542360

  5. HTTP缓存技术,304和200有何区别

    为什么有的缓存是 200 OK (from cache),有的缓存是 304 Not Modified 呢?很简单,看运维是否移除了 Entity Tag.移除了,就总是 200 OK (from c ...

  6. 一个容易被忽视的css选择器

    之前学的的迷糊了,也不知道什么会什么不会了,跑去面试了.别人列出一堆css选择器,本以为选择器没啥的,结果到那个多类选择器翻车了,.a.b选择同时含a,b类名的,很尴尬所以回来仔细整理了一下.目前根据 ...

  7. uvm_analysis_port——TLM1事务级建模方法(二)

    UVM中的TLM1端口,第一类是用于uvm_driver 和uvm_sequencer连接端口,第二类是用于其他component之间连接的端口,如uvm_monitor和uvm_scoreboard ...

  8. Android商城开发系列(十三)—— 首页热卖商品布局实现

    热卖商品布局效果如下图: 这个布局跟我们上节做的推荐是一样的,也是用LinearLayout和GridView去实现的,新建一个hot_item.xml,代码如下所示: <?xml versio ...

  9. jQuery-动画animate() 方法操作 CSS 属性

    语法: $(selector).animate({params},speed,callback); 多个params 之间用逗号(,)隔开. 必须使用 Camel 标记法书写所有的属性名,比如,必须使 ...

  10. 交互ajax

    原生的js封装ajax1.创建ajax对象var oAjax=new XMLHttpRequest();//不兼容IE6var oAjax=new ActiveXobject('Microsoft.X ...