题目链接:http://poj.org/problem?id=2104

K-th Number
Time Limit: 20000MS   Memory Limit: 65536K
Total Submissions: 64277   Accepted: 22615
Case Time Limit: 2000MS

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.

Source

Northeastern Europe 2004, Northern Subregion

划分树:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+;
const int MAXN = 1e5+; int tree[][MAXN];
int sorted[MAXN];
int toleft[][MAXN]; void build(int l, int r, int dep)
{
if(l==r) return;
int mid = (l+r)>>;
int same = mid-l+;
for(int i = l; i<=r; i++)
if(tree[dep][i]<sorted[mid])
same--; int lpos = l, rpos = mid+;
for(int i = l; i<=r; i++)
{
if(tree[dep][i]<sorted[mid])
tree[dep+][lpos++] = tree[dep][i];
else if(tree[dep][i]==sorted[mid] && same>)
{
tree[dep+][lpos++] = tree[dep][i];
same--;
}
else
tree[dep+][rpos++] = tree[dep][i];
toleft[dep][i] = toleft[dep][l-] + lpos - l;
} build(l, mid, dep+);
build(mid+, r, dep+);
} int query(int L, int R, int l, int r, int dep, int k)
{
if(l==r) return tree[dep][l];
int mid = (L+R)>>;
int cnt = toleft[dep][r] - toleft[dep][l-]; if(cnt>=k)
{
int newl = L + toleft[dep][l-] - toleft[dep][L-];
int newr = newl + cnt - ;
return query(L, mid, newl, newr, dep+, k);
}
else
{
int newr = r + toleft[dep][R] - toleft[dep][r];
int newl = newr - (r-l-cnt);
return query(mid+, R, newl, newr, dep+, k-cnt);
}
} int main()
{
int n, m;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(tree, , sizeof(tree));
for(int i = ; i<=n; i++)
{
scanf("%d",&tree[][i]);
sorted[i] = tree[][i];
}
sort(sorted+, sorted++n);
build(, n, );
int s, t, k;
while(m--)
{
scanf("%d%d%d",&s,&t,&k);
printf("%d\n", query(,n,s,t,,k));
}
}
return ;
}

主席树(循环):

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e5+;
const int M = MAXN*; int n, q, m, tot;
int a[MAXN], t[MAXN];
int T[MAXN], lson[M], rson[M], c[M]; void Init_hash()
{
for(int i = ; i<=n; i++)
t[i] = a[i];
sort(t+,t++n);
m = unique(t+,t++n)-(t+);
} int hash(int x)
{
return lower_bound(t+,t++m, x)-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 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()
{
while(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 <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 1e5+;
const int M = MAXN*; int n, q, m, tot;
int a[MAXN], t[MAXN];
int T[MAXN], lson[M], rson[M], c[M]; void Init_hash()
{
for(int i = ; i<=n; i++)
t[i] = a[i];
sort(t+,t++n);
m = unique(t+,t++n)-(t+);
} int hash(int x)
{
return lower_bound(t+,t++m, x)-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 update(int root, int l, int r, int pos, int val)
{
int newroot = tot++;
if(l==r)
{
c[newroot] = c[root] + val;
return newroot;
}
int mid = (l+r)>>;
if(pos<=mid)
{
lson[newroot] = update(lson[root],l,mid,pos,val);
rson[newroot] = rson[root];
}
else
{
rson[newroot] = update(rson[root],mid+,r,pos,val);
lson[newroot] = lson[root];
}
c[newroot] = c[lson[newroot]] + c[rson[newroot]];
return newroot;
} int query(int left_root, int right_root, int l, int r, int k)
{
if(l==r) return l; int mid = (l+r)>>;
if(c[lson[left_root]]-c[lson[right_root]]>=k)
return query(lson[left_root],lson[right_root],l,mid,k);
else
return query(rson[left_root],rson[right_root],mid+,r,k-(c[lson[left_root]]-c[lson[right_root]]));
} int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
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+],,m,pos,);
}
while(q--)
{
int l, r, k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n", t[query(T[l],T[r+],,m,k)]);
}
}
}

POJ2104 K-th Number —— 静态区间第k小的更多相关文章

  1. POJ2104 K-th Number 静态区间第k最值 平方分割

    干掉这道题的那一刻,我只想说:我终于**的AC了!!! 最终内存1344K,耗时10282ms,比起归并树.划分树以及其他各种黑科技,这个成绩并不算光彩⊙﹏⊙ 但至少,从最初的无数次TLE到最终的AC ...

  2. poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板

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

  3. HDU3473--Minimum Sum(静态区间第k大)

    Minimum Sum Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tota ...

  4. 数据结构2 静态区间第K大/第K小

    给定数组$A[1...N]$, 区间$[L,R]$中第$K$大/小的数的指将$A[L...R]$中的数从大到小/从小到大排序后的第$K$个. "静态"指的是不带修改. 这个问题有多 ...

  5. Dynamic Rankings || 动态/静态区间第k小(主席树)

    JYF大佬说,一星期要写很多篇博客才会有人看 但是我做题没有那么快啊QwQ Part1 写在前面 区间第K小问题一直是主席树经典题=w=今天的重点是动态区间第K小问题.静态问题要求查询一个区间内的第k ...

  6. 主席树初步学习笔记(可持久化数组?静态区间第k大?)

    我接触 OI也快1年了,然而只写了3篇博客...(而且还是从DP跳到了主席树),不知道我这个机房吊车尾什么时候才能摸到大佬们的脚后跟orz... 前言:主席树这个东西,可以说是一种非常畸形的数据结构( ...

  7. 静态区间第k大(归并树)

    POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...

  8. 主席树学习笔记(静态区间第k大)

    题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...

  9. 主席树(静态区间第k大)

    前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...

随机推荐

  1. 【重点突破】——第三方绘图工具FusionCharts.js的使用详解

    一.引言 项目组中,经常会因为绘制图表的繁杂度,衡量会不会使用第三方绘图工具,如果自己做很困难,成本使用高于第三方绘图工具库,就会使用.很多人使用的是Chart.js,因为它是免费使用的,不过,缺点就 ...

  2. Android5 Zygote 与 SystemServer 启动流程分析

    Android5 Zygote 与 SystemServer 启动流程分析 Android5 Zygote 与 SystemServer 启动流程分析 前言 zygote 进程 解析 zygoterc ...

  3. SqlServer 垂直分表

    当单表数据太多时.我们能够水平划分,參考 SqlServer 分区视图实现水平分表 ,水平划分能够提高表的一些性能. 而 垂直分表 则相对非常少见到和用到,由于这可能是数据库设计上的问题了.假设数据库 ...

  4. Android微信分享功能实例+demo

    Android微信分享功能实例 1 微信开放平台注册 2 获得appId,添加到程序中,并运行程序 3 使用应用签名apk生成签名,添加到微信开放平台应用签名,完成注册 4 测试分享功能. 有问题请留 ...

  5. 利用php调用so库文件中的代码

    某个功能被编译到so文件中,那么如何通过php来调用它?一个方法是写一个php模块(php extension),在php中调用该模块内的函数,再通过该模块来调用so中的函数.下面做一个简单的例子,使 ...

  6. oracle中视图v$sql的用途

    1.获取正在执行的sql语句.sql语句的执行时间.sql语句的等待事件: select a.sql_text,b.status,b.last_call_et,b.machine,b.event,b. ...

  7. Mysql 5.7.18 利用 MySQL proxies_priv(模拟角色)实现类似用户组管理

    利用 MySQL proxies_priv(模拟角色)实现类似用户组管理 角色(Role)可以用来批量管理用户,同一个角色下的用户,拥有相同的权限. MySQL5.7.X以后可以模拟角色(Role)的 ...

  8. Tomcat 7.0 servlet @WebServlet

    在使用tomcat7.0+eclipse j2ee时,新建Dynamic Web Project时, 会让选择是否生成web.xml.无论选择与否,此时新建一个servlet, 可以不在web.xml ...

  9. iOS 逆向 - Class-dump 安装和使用方法

    1.下载安装包 http://stevenygard.com/projects/class-dump/,这里我下载的是 class-dump-3.5.dmp.然后把下载下来的 dmg 打开,复制文件里 ...

  10. ios --转载获ipa 的图片资源

      突然想起当初刚学习iOS的时候,就经常通过抓包和提取素材的方式来模仿App,今天就教大家如何一步步提取App的素材! 大家是否有过想要获取别人的素材的想法?看到某些App的资源很不错,很想导出来用 ...