[poj 2104] K-th Number【主席树】

传送门:http://poj.org/problem?id=2104

保存模版。

#include <cstdio>
#include <algorithm>
#include <cstring>

// Sora Sai Gou!!!

const int maxn = 100005, maxm = 5005, maxv = 2000005, nil = maxv - 1;

int n, m, a[maxn], b[maxn], siz[maxv], ch[maxv][2], root[maxv], cnt;
int t1, t2, t3;

inline int fndidx(int key) {
	int left = 1, right = n, mid;
	while (left < right) {
		mid = (left + right) >> 1;
		if (a[mid] < key) {
			left = mid + 1;
		}
		else {
			right = mid;
		}
	}
	return left;
}
void ist(int & ima, int p, int key, int ql, int qr) {
	if (!ima) {
		ima = ++cnt;
	}
	siz[ima] = siz[p] + 1;
	if (ql == qr) {
		return;
	}
	int mid = (ql + qr) >> 1;
	if (key <= mid) {
		ch[ima][1] = ch[p][1];
		ist(ch[ima][0], ch[p][0], key, ql, mid);
	}
	else {
		ch[ima][0] = ch[p][0];
		ist(ch[ima][1], ch[p][1], key, mid + 1, qr);
	}
}
inline int qry (int l, int r, int kth) {
	--l;
	int left = 1, right = n, mid, p1 = root[l], p2 = root[r], tem;
	while (left < right) {
		tem = siz[ch[p2][0]] - siz[ch[p1][0]];
		mid = (left + right) >> 1;
		if (kth <= tem) {
			p2 = ch[p2][0];
			p1 = ch[p1][0];
			right = mid;
		}
		else {
			kth -= tem;
			p2 = ch[p2][1];
			p1 = ch[p1][1];
			left = mid + 1;
		}
	}
	return a[left];
}

int main(void) {
	//freopen("in.txt", "r", stdin);
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", a + i);
	}
	memcpy(b, a, sizeof b);
	std::sort(a + 1, a + n + 1);
	for (int i = 1; i <= n; ++i) {
		b[i] = fndidx(b[i]);
	}

	for (int i = 1; i <= n; ++i) {
		ist(root[i], root[i - 1], b[i], 1, n);
	}
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &t1, &t2, &t3);
		printf("%d\n", qry(t1, t2, t3));
	}
	return 0;
}

  

时间: 2024-11-07 23:04:20

[poj 2104] K-th Number【主席树】的相关文章

【POJ 2104】 K-th Number 主席树模板题

达神主席树讲解传送门:http://blog.csdn.net/dad3zz/article/details/50638026 2016-02-23:真的是模板题诶,主席树模板水过.今天新校网不好,没有评测,但我立下flag这个代码一定能A.我的同学在自习课上考语文,然而机房党都跑到机房来避难了\(^o^)/~ #include<cstdio> #include<cstring> #include<algorithm> #define for1(i,a,n) for(i

AcWing 255. 第K小数 (主席树写法)

区间k小数是主席树的模板题目,如果区间不包含,用莫队+权值线段树也能解 主席树是可持久化线段树,所为可持久化,就是每次只新增不一样的节点,而保留前面的版本,这样可以做到查询. 如果询问时1-r,那么直接主席树,询问的是l-r,就用到前缀和思想,具体看代码注释 #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #include<vector> #inclu

POJ 2104:K-th Number(主席树静态区间k大)

题目大意:对于一个序列,每次询问区间[l,r]的第k大树. 分析: 主席树模板题 program kthtree; type point=record l,r,s:longint; end; var t:array[0..100000*50]of point; a,b,id,root:array[0..100000]of longint; n,i,m,x,y,k,v,len:longint; procedure qsort(l,h:longint); var i,j,t,m:longint; b

POJ 2104:K-th Number(整体二分)

http://poj.org/problem?id=2104 题意:给出n个数和m个询问求区间第K小. 思路:以前用主席树做过,这次学整体二分来做.整体二分在yr大佬的指点下,终于大概懂了点了.对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了. 在这题二分可行的答案,根据这个答案,把询问操作丢在左右两个队列里面分别递归继续按这样处理.注释里写的很详细. 1 #include <iostream> 2 #include <cstdlib> 3 #

POJ2104 K-th Number[主席树]

K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 51440   Accepted: 17594 Case Time Limit: 2000MS Description You are working for Macrohard company in data structures department. After failing your previous task about key inse

zoj2112 主席树动态第k大 (主席树&amp;&amp;树状数组)

Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with the query like to simply find the k-th smallest number of the given N numbers. They

hdoj 2665 Kth number主席树裸

Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 9417    Accepted Submission(s): 2938 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The fi

[POJ2761]Feed the dogs(静态区间第k小,主席树)

题目链接:http://poj.org/problem?id=2761 题意:如题 主席树只能用模版,好菜. 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm>

poj2104 K-th Number 主席树入门;

题目链接:K-th Number 题解:我们先把数组离散离散化一下,然后先不考虑L,R的区间的关系,我们有一个棵线段树sum[]保存的是第几大到第几大出现的个数,这样我们想要询问这颗线段数的第k大是多少可以在log(n)次下就找到,但是区间的不同,一颗线段树是解决不了的,那我们如何得到L,R区间的sum数组呢?.我们可以建N棵线段树,第一棵树是空树,然后第一个数过来我们再建一课线段树在原来树的基础上,加上这个数对sum数组的贡献,这样从第一个到第N个建N棵线段树建好,我们可以发现sum[]有前缀

4504: K个串 主席树+优先队列

这道题因为有一个数在序列中出现多次只算一次的限制.我们可以这样搞.假设在当前题意下求给定右端点的区间最值.那么我们可以预处理出每个数前一次出现的位置pre[i] .接下来从左到右加入每一个值,就是在 pre[i] + 1 —— i 这个区间内加上 v[i] 的值,这样就可以得到以当前 i 点为右端点的各个区间的值(很明显维护一下最值就好了).接下来很明显有n个版本的线段树(如果你说一开始那个空的线段树也算一个版本的话,就有n+1个),那就要用主席树动态开点.而取第K大值的操作有点像超级钢琴,不过