您的位置:首页 > 其它

蓝桥杯_ 算法训练 区间k大数查询

2018-03-20 16:30 302 查看
问题描述给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个。
输入格式第一行包含一个数n,表示序列长度。
第二行包含n个正整数,表示给定的序列。
第三个包含一个正整数m,表示询问个数。
接下来m行,每行三个数l,r,K,表示询问序列从左往右第l个数到第r个数中,从大往小第K大的数是哪个。序列元素从1开始标号。
输出格式总共输出m行,每行一个数,表示询问的答案。样例输入5
1 2 3 4 5
2
1 5 2
2 3 2样例输出4
2数据规模与约定对于30%的数据,n,m<=100;
对于100%的数据,n,m<=1000;
保证k<=(r-l+1),序列中的数<=106。

采用在特定区间的归并排序的方法,因为归并排序在书写上比较舒服,或者说是跟线段树有一小部分有点相似,所以总是喜欢写归并排序。并且归并排序不管在什么情况下时间复杂度都是O(nlogn)所以比较均衡一些。#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <math.h>
#define MAX_N 201000
#define MAX_M 21000
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int MAXN = 1e3+10;
int temp [MAXN];

void become_one(int a[],int l,int mid,int r)
{
int cnt = 0;
int index = 0;
int index_l = l;
int index_r = mid+1;
while(index_l <= mid && index_r <= r)
{
if (a[index_l] < a[index_r])
{
temp[index++] = a[index_l ++];
}
else
{
temp[index++] = a[index_r ++];
}
}
while(index_l <= mid )
temp[index++] = a[index_l++];
while(index_r <= r)
temp[index++] = a[index_r++];
index = 0;
for(int i = l;i <= r;i ++)
a[i] = temp[index++];
}

void Sort(int a[],int l, int r)
{
if (l == r)
return ;
int mid = (l+r) >> 1;
Sort(a,l,mid);
Sort(a,mid+1,r);
become_one(a,l,mid,r);
}

int main()
{
int n;
int a[MAXN];
int b[MAXN];
scanf("%d",&n);
for(int i = 0;i < n;i ++)
scanf("%d",&a[i]);
int m;
scanf("%d",&m);
int l,r,k;
for(int i =0 ;i < m;i ++)
{
for(int j =0 ;j < n;j++)
{
b[j] = a[j];
}
scanf("%d%d%d",&l,&r,&k);
Sort(b,l-1,r-1);
printf("%d\n",b[r-k]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息