[HDOJ2665] Kth number

Problem Description
Give you a sequence and ask you the kth big number of a inteval.

Input

The first line is the number of the test cases.
For each test case, the first line contain two integer n n n and m m m ( n n n, m m m <= 100000), indicates the number of integers in the sequence and the number of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s , t , k s, t, k s,t,k.
[ s s s, t t t] indicates the interval and k k k indicates the kth big number in interval [ s s s, t t t]

Output

For each test case, output m lines. Each line contains the kth big number.

Sample Input

1 10 1 1 4 2 3 5 6 7 8 9 0 1 3 2

Sample Output

2

大意
一定是我英语不好
给定一个长为 n n n的数组,有 m m m次询问,每次询问输入一个区间 [ l , r ] [l,r] [l,r]及一个 k k k,输出区间 [ l , r ] [l,r] [l,r]内第 k k k的数字。

思路
静态区间第 k k k大(小),主席树板子。

AC代码

#include<stdio.h>
#include<map>
#include<queue>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#define MOD 10000000007
#define N 100005
typedef long long LL;
using namespace std;
typedef struct node{
	int lson,rson,va;//va:权值   主席树 
}node;
int tot,n,m,te,len,s,t,k;
int a[N],T[N];
node tree[N<<5];
int R[N];
void init()
{
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);T[i]=a[i];
	}
	sort(T+1,T+n+1);
	len=unique(T+1,T+n+1)-T-1;
}
void build(int &root,int l,int r)
{
	root=++tot;
	if(l==r)return;
	int mid=(l+r)/2;
	build(tree[root].lson,l,mid);
	build(tree[root].rson,mid+1,r);
	return;
}
int find(int target)
{
	return lower_bound(T+1,T+len+1,target)-T;
}
void insert(int pre,int &root,int l,int r,int pos)
{
	tree[++tot]=tree[pre];root=tot;
	if(l==r) 
	{
		tree[root].va++;return;
	}
	int mid=(l+r)/2;
	if(pos>mid) insert(tree[root].rson,tree[root].rson,mid+1,r,pos);else insert(tree[root].lson,tree[root].lson,l,mid,pos);
	tree[root].va++;
	return;
}
int query(int from,int to,int k,int l,int r)
{
	if(l==r)return l;
	int sum=tree[tree[to].lson].va-tree[tree[from].lson].va;
	int mid=(l+r)/2;
	if(k>sum)
		return query(tree[from].rson,tree[to].rson,k-sum,mid+1,r);
	else 
		return query(tree[from].lson,tree[to].lson,k,l,mid);
}
int main()
{
	scanf("%d",&te);
	while(te--)
	{
		scanf("%d%d",&n,&m);
		init();
		tot=0;
		build(R[0],1,n);
		for(int i=1;i<=n;i++) insert(R[i-1],R[i],1,len,find(a[i]));//insert函数实际上是将原始数据离散化后的值插入权值线段树,故此时的l=1,r=离散化后剩余的元素数 
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d%d",&s,&t,&k);
			printf("%d\n",T[query(R[s-1],R[t],k,1,len)]);
		}
	}
	return 0;
}

你可能感兴趣的:(数据结构-主席树,思想-离散化)