题目链接: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. 2017.2.13 开涛shiro教程-第十二章-与Spring集成(一)配置文件详解

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第十二章-与Spring集成(一)配置文件详解 1.pom.xml ...

  2. HashSet和SortSet对比--c#学习笔记

    微软在 .NET 3.5 新增了一个 HashSet 类,在 .NET 4 新增了一个 SortedSet 类. .NET Collection 函数库的 HashSet.SortedSet 这两个泛 ...

  3. FreeMark的list应用

    语法:<#if></#if>后台传送List,前台html页面中获取该list并显示: <#if userList?exists> <#list userLi ...

  4. dede程序打开install安装时出现dir

    刚在网上找了个开源的dede程序,打开install安装时出现dir.解决方法例如以下: 1.删除install下的index.html和install_lock.txt(有的是要删除install. ...

  5. 雕刻效果的实现【OpenCV+QT】

    雕刻能够区分为凸雕和凹雕. 凸雕基右下角的点减去左上角的点. 凹雕是左上角的点减去右下角的点. [效果图] 由于进行了缩放.效果看起来差一些.

  6. hdu1316

    链接:pid=1316" target="_blank">点击打开链接 题意:问区间[a,b]中有多少斐波那契数 代码: #include <iostream ...

  7. jquery文档处理如after错误

    $('.foo').after('<li>0<li>')会添加两个元素 $('.foo').after('<li>o</li>')只会添加一个元素 所以 ...

  8. Excel COM组件使用的注意事项和一些权限问题(转载)

    1.实例化Excel的COM组件的时候,不要直接调用类,要用Microsoft提供的接口 原来的写法:Excel.ApplicationClass excelApp = new Excel.Appli ...

  9. 有两个好友A和B,住在一片长有蘑菇的由n*m个方格组成的草地,A在(1,1),B在(n,m)。现在A想要拜访B,由于她只想去B的家,所以每次她只会走(i,j+1)或(i+1,j)这样的路线,在草地上有k个蘑菇种在格子里(多个蘑菇可能在同一方格),问:A如果每一步随机选择的话(若她在边界上,则只有一种选择),那么她不碰到蘑菇走到B的家的概率是多少?

    第二种方法:首先分析题意,可用概率的方法来计算,做了好几道百度的题目,觉得大多数是再考概率论,所以首先要弄懂题意,最后做题前把公式写出来,这样编码时才能游刃有余. 本题中下面的第一种用迭代枚举的方法来 ...

  10. Volley框架载入网络图片

    Android开发中,载入网络server的图片是非经常常使用的.当然我们能够自己写server接口去实现,只是要做到server性能 优越的话,开发起来比較麻烦点.所以本博客要介绍Volley框架进 ...