PS:如果你看完了下面的内容,那很不幸,很多都是没必要的。。。因为我才发现,long int 就是int !(可恶
也就是说下面关于内存的什么long long 好像都是我YY出来的,因为数据类型题目已经保证了是int ...... 惭愧惭愧,博客也懒得改了,以下为原答案:
题意:给两个有序序列,输出两个序列合并以后的中位数。
难点:我很惭愧,这题没有用到高深的算法,没有用到优秀的数据结构,没有扯到玄学的数学知识,没有出现脑残的题意不清。然鹅,我就是没A。能力着实不足呀。
此题N小于2×10^5,本题最大的难度不是时间问题。而是空间!
1、本题我在考研复习的时候在数据结构的书上看到类似的,使用一种类似二分的思想,可以在O(logn)的时间内实现,而不是O(n)。但是后来发现,那题虽然和本题一样,都是给了两个有序的序列输出中位数,但是本题的两个序列是不定长的!使得问题复杂化,不能使用二分了。
2、最重要的一点,在提交完O(n)的代码之后,“内存溢出”的错误提示,我才明白本题的卡内存才是难点。也就是说不能存储两个long long 的数组,否则就会内存溢出。
3、于是我只存储第一个序列,采用第二个序列只读第一个数的办法,这样理论上内存节省了一半,应该就不会内存溢出了。然鹅,这样写的程序,要兼顾两个序列不定长带来的,对于“哪个队列更短导致的队列先空队列”的边界讨论,大大影响的代码的书写。导致我程序错误的同时,内存依然溢出了!
4、在挣扎了一个晚上之后,学习了柳神的代码,最后发现了她的代码与解题思路更加优化,最后借鉴了柳神的代码才AC。。。柳神太厉害了。。。(别人的代码都已经过不了了,因为18年3月份之后PAT对此题进行了内存溢出的强化样例,直接匹配或者是队列存储都会溢出的!)
在此总结一下,本题我(借鉴学习之后)的思路:
1)本题的内存限制是1.5MB,输入一个序列最长2×10^5个数,每个数都是 long int 型的;而如果假设所有数字都是int型的,那么每个数的存储是4B,那么一个序列最长的情况下就要占据0.8MB的内存。如果是long int,那就直接1.6MB了。这么计算之后,我才明白为什么柳神说:“本题的long int中的数据不可能是答案,都是干扰数据。”
题目的AC思路,就是输出两个序列的更小的那项,输出前1/2总数的项数,下一个就是中位数了!
而对于序列存储的处理办法是,开队列的时候,就开 int型的队列,输入的数据,大于int就用int的最大值去代替,这样就可以存下第一个序列了!
2)第二个序列,用int型存也会内存溢出,柳神的办法很有趣——每一次读取第二个序列的输入数的之后,都进行一次比较,那么要不就是序列1的队列长度减一,要么就是序列2的队列长度减一,使得总程序的内存占用没有增加!这样就可以使得内存不会溢出了!
而如果是把第二个序列全存下来是不现实的;如果只读入第二个序列的第一个数字,只在第二个序列小的时候再读入第二个序列的下一个数字,这样书写代码逻辑的时候又很烦,所以总的来说,柳神这个写法更好诶。
3)考虑一下边界,我是把队空判断逻辑放在总的比较循环体中了,所以要考虑两个队列谁空的情况即可。
Code:
上代码,和优秀还是差得很远啊。
#include<bits/stdc++.h>
using namespace std;
#define inf 200009
#define INF 0x3f3f3f3f
#define loop(x,y,z) for(x=y;x<z;x++)
#define ll long long
queue<int>a,b;
int len1,len2;
void debug(int i,char *s)//debug输出用
{
printf("debug: %d %s\n",i,s);
}
void Input()
{
int i,cnt;
ll t;
scanf("%d",&len1);
loop(i,0,len1)
{
scanf("%lld",&t);
t=min(t,(ll)INT_MAX);
a.push(t);
}
scanf("%d",&len2);
int sum=len1+len2;
if(sum%2==0)sum=sum/2-1;
else sum/=2;//计算出要吐掉多少个
i=cnt=0;
while(1)
{
if(i<len2)
{
scanf("%lld",&t);
t=min(t,(ll)INT_MAX);
b.push(t);
i++;
}
if(cnt==sum)break;
if(a.empty())//有一方队列空,边界
{
b.pop();//debug(1,"a empty");
cnt++;
continue;
}
else if(b.empty())
{
a.pop();//debug(2,"b empty");
cnt++;
continue;
}
if(a.front()<b.front())
a.pop();//debug(3,"a small");
else
b.pop();//debug(4,"b small");
cnt++;
}
if(a.empty())printf("%d\n",b.front());
else if(b.empty())printf("%d\n",a.front());
else printf("%d\n",min(a.front(),b.front()));
}
int main()
{
Input();
return 0;
}