题目链接: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. Linux测网速

    $ wget https://raw.github.com/sivel/speedtest-cli/master/speedtest_cli.py$ chmod a+rx speedtest_cli. ...

  2. Interleaving String——是否由两个string交叉、DP

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...

  3. 【Excle数据透视】如何升序排列字段列表中的字段

    数据透视表创建完毕,那么如何将字段列表中的字段修改为升序排列呢? 解决方案 更改"字段列表"为按"升序"排列 步骤 单击数据透视表任意单元格→右键单击→数据透视 ...

  4. npm安装package.json

    npm安装package.json时,直接转到当前项目目录下,用命令npm install 或npm install --save-dev安装即可,自动将package.json中的模块安装到node ...

  5. 【转载】ASP.Net请求处理机制初步探索之旅 - Part 3 管道

    开篇:上一篇我们了解了一个ASP.Net页面请求的核心处理入口,它经历了三个重要的入口,分别是:ISAPIRuntime.ProcessRequest().HttpRuntime.ProcessReq ...

  6. delphi 解析Json格式(转自:http://blog.csdn.net/jayqiang/article/details/7066824)

    SuperObject 是开源的 Delphi 的 JSON 工具包,可生成 JSON 数据以及进行 JSON 解析. unit Unit6; interface uses Windows, Mess ...

  7. string去空格

    众所周知,string字符串去除空格的方法有trim()和replace(),区别在于trim()去首尾的空格,但是不能去中间的,而replace可以去除所有的空格. string data1=&qu ...

  8. 史上最浅显易懂的Git教程1

    工作区(Working Directory)就是你在电脑里能看到的目录, 工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库. Git的版本库里存了很多东西,其中最重要的就是称为stag ...

  9. 开源大数据引擎:Greenplum 数据库架构分析

    Greenplum 数据库是最先进的分布式开源数据库技术,主要用来处理大规模的数据分析任务,包括数据仓库.商务智能(OLAP)和数据挖掘等.自2015年10月正式开源以来,受到国内外业内人士的广泛关注 ...

  10. 【Caffe】利用log文件绘制loss和accuracy(转载)

    (原文地址:http://blog.csdn.net/liuweizj12/article/details/64920428) 在训练过程中画出accuracy 和loss曲线能够更直观的观察网络训练 ...