划分树 Kth number

Kth number
Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

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 and m (n, 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] indicates the interval and k indicates the kth big number in interval [s, 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
 

#include <iostream>
#include <algorithm>
#include <string.h>
#define MAXN 100010

using namespace std;

class Node
{
	public:
	
	int l, r;
};

class SGtree
{
	public:
	
	Node node[MAXN << 2];
	
	int num_left[20][MAXN];
	int sg_node[20][MAXN];
	int parray[MAXN];
	
	void init();
	void Maketree(int i, int d, int l, int r);
	int Query(int i, int d, int x, int y, int k);
}tree;

void SGtree::init()
{
	memset(num_left, 0, sizeof(0));
	memset(sg_node, 0, sizeof(sg_node));
	memset(node, 0, sizeof(node));
}

void SGtree::Maketree(int o, int d, int l, int r)
{
	node[o].l = l;
	node[o].r = r;
	if (l == r)
	{
		return ;
	}
	
	int mid = (l + r) >> 1;
	int issame = mid - l + 1;
	
	for (int i = l; i <= r; i++)
	{
		if (sg_node[d][i] < parray[mid])
		{
			issame--;
		}
	}
	
	int pl = l, pr = mid + 1;
	
	for (int i = l; i <= r; i++)
	{
		if (i == l)
		{
			num_left[d][i] = 0;
		}
		else
		{
			num_left[d][i] = num_left[d][i - 1];	
		}
		
		if (sg_node[d][i] < parray[mid])
		{
			num_left[d][i]++;
			sg_node[d + 1][pl++] = sg_node[d][i];
		}
		if (sg_node[d][i] > parray[mid])
		{
			sg_node[d + 1][pr++] = sg_node[d][i];
		}
		if (sg_node[d][i] == parray[mid])
		{
			if (issame > 0)
			{
				issame--;
				num_left[d][i]++;
				sg_node[d + 1][pl++] = sg_node[d][i];
			}	
			else
			{
				sg_node[d + 1][pr++] = sg_node[d][i];	
			}
		}
	}
	
	Maketree(2 * o, d + 1, l, mid);
	Maketree(2 * o + 1, d + 1, mid + 1, r);
}

int SGtree::Query(int i, int d, int x, int y, int k)
{
	int l = node[i].l;
	int r = node[i].r;
	int mid = (l + r) >> 1;
	
	if (l == r)
	{
		return sg_node[d][x];
	}
	
	int lnum, ltornum;
	
	if (x == node[i].l)
	{
		lnum = 0;
	}
	else
	{
		lnum = num_left[d][x - 1];
	}
	
	ltornum = num_left[d][y] - lnum;
	
	if (ltornum >= k)
	{
		return Query(i * 2, d + 1, l + lnum, l + lnum + ltornum - 1, k);
	}
	else
	{
		int a = x - l - lnum;
		int b = y - x - ltornum;
		return Query(i * 2 + 1, d + 1, mid + a + 1, mid + a + b + 1, k - ltornum);
	}
}

void input()
{
	int t, n, m, x, y, k;
	cin >> t;
	
	while (t--)
	{
		scanf("%d %d", &n, &m);
		tree.init();
		
		for (int i = 1; i <= n; i++)
		{
			scanf("%d", &tree.parray[i]);
			tree.sg_node[1][i] = tree.parray[i];
		}
		
		sort(tree.parray + 1, tree.parray + n + 1);
		tree.Maketree(1, 1, 1, n);

		while (m--)
		{
			scanf("%d %d %d", &x, &y, &k);
			printf("%d\n", tree.Query(1, 1, x, y, k));
		}
	}
}

int main()
{
	input();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值