题目描述
Given an increasing sequence S of N integers, the median is the number at the middle position. For example, the median of S1 = { 11, 12, 13, 14 } is 12, and the median of S2 = { 9, 10, 15, 16, 17 } is 15. The median of two sequences is defined to be the median of the nondecreasing sequence which contains all the elements of both sequences. For example, the median of S1 and S2 is 13.
Given two increasing sequences of integers, you are asked to find their median.
Input Specification:
Each input file contains one test case. Each case occupies 2 lines, each gives the information of a sequence. For each sequence, the first positive integer N (≤2×10^5) is the size of that sequence. Then N integers follow, separated by a space. It is guaranteed that all the integers are in the range of long int.
Output Specification:
For each test case you should output the median of the two given sequences in a line.
题目大意
给定一个包含N个整数的递增序列S,中位数是指在中间位置的数。例如,S1={11,12,13,14}的中位数是12,S2={9,10,15,16,17}的中位数是15。两个序列的中位数被定义为包含两个序列所有元素的非递减的序列的中位数。例如,S1和S2的中位数是13。
给两个递增的整数序列,你需要找出他们的中位数。
输入说明
每一个输入文件包含一个测试用例。每个测试用例占两行,每一行给出一个序列的信息。对于每一个序列,第一个正整数N(<= 2x10^5)是序列的大小。然后跟着N个由空格分隔的整数。保证所整数的范围都能用long int来表示。
输出说明
每一个测试用例你应该将中位数输出到一行中。
题目分析
定义一个数组S1
,将第一个序列的全部数据存储下来。根据两个序列的长度,可以求得将两个序列按非递减合并成一个序列时,中位数的下标。假设两个序列的长度分别为n1
和n2
,中位数的下标为mid = (n1 + n2 + 1) / 2 - 1
,至于为什么,大家可以自行推导。
这个题最直接的思路就是将两个序列合并成一个序列,再求中位数,但是这种方法会导致运行超时。仔细想一下,这道题给的数据量虽然可能很大,但是我们只需要其中的一个数,所以没必要将全部数据进行排序。
我所采用的方法是,将第一个序列的数据全部存储到数组S1
中,读取第二个序列时,不进行存储,而是定义一个索引下标index
,比较读入的数据和S1[index]
的大小关系,若读入的数据大,则让index
自加,直到读入的数据小于等于S1[index]
。这里有一个问题就是若读入的数据比第一个序列的所有数都大,这样可能会引起数组越界。解决方法是在第一个序列的最后添加一个最大的整数,即S1[n1] = INT_MAX
,这样就不用担心index
一直自加导致数组越界了。
当S1[index]
大于等于读入的数据时,假设读入的是第二个序列的第i
个数据,那么index+i
就是将两个序列按非递减排序后,当前读入的数据所在的位置。比较mid
和index+i
的大小关系,如果相等,那么当前读入的数据就是中位数。如果index+i
大于mid
,那么说明中位数在序列S1
中,并且是在从S1[index]
开始向前数的第index+i-mid
个位置。所以此种情况的中位数下标为index - (index +i -mid)
。
#include <bits/stdc++.h>
using namespace std;
int S1[200005];
int main()
{
ios::sync_with_stdio(false);//提高cin和cout的速度
int n1, n2,index = 0;//index为第一个序列的索引
int element;//序列2的元素
cin >> n1;
for (int i = 0; i < n1; i++)
cin >> S1[i];
S1[n1] = INT_MAX;//防止访问S1时越界
cin >> n2;
int mid = (n1 + n2 + 1) / 2 - 1;//假设将S1和S2按非递减排序,mid就是median的索引
for (int i = 0; i < n2; i++) {
cin >> element;
for (; S1[index] < element; index++);
if (index + i == mid) {
cout << element;
return 0;
}
else if (index + i > mid) {
cout << S1[mid - i];
return 0;
}
}
cout << S1[mid - n2];
}