For this problem, you will write a program that reads in a sequence of 32-bit signed integers. After each odd-indexed value is read, output the median (middle value) of the elements received so far.
Input
The first line of input contains a single integer P, (1 ≤ P ≤ 1000), which is the number of data sets that follow. The first line of each data set contains the data set number, followed by a space, followed by an odd decimal integer M, (1 ≤ M ≤ 9999), giving the total number of signed integers to be processed. The remaining line(s) in the dataset consists of the values, 10 per line, separated by a single space. The last line in the dataset may contain less than 10 values.
Output
For each data set the first line of output contains the data set number, a single space and the number of medians output (which should be one-half the number of input values plus one). The output medians will be on the following lines, 10 per line separated by a single space. The last line may have less than 10 elements, but at least 1 element. There should be no blank lines in the output.
Sample Input
3 1 9 1 2 3 4 5 6 7 8 9 2 9 9 8 7 6 5 4 3 2 1 3 23 23 41 13 22 -3 24 -31 -11 -8 -7 3 5 103 211 -311 -45 -67 -73 -81 -99 -33 24 56
Sample Output
1 5 1 2 3 4 5 2 5 9 8 7 6 5 3 12 23 23 22 22 13 3 5 5 3 -3 -7 -3
题意:每组M个数,然后对于每组数读入的时候,只要读入了奇数个的数,就求出先前读入数的中位数,然后输出
思路:可以采用两个优先队列的做法,如果当前读入的数>当前中位数,插入小根堆,否则插入大根堆,这样实际上就维护了中位数相邻两侧的值。
然后维护 num【小根堆】 - num【大根堆】 <= 1,就是维护中位数两侧的数量应当均分,这样小根堆的top,即是中位数
1 #include<cstdio> 2 #include<iostream> 3 #include<queue> 4 using namespace std; 5 6 int t; 7 int cas,n; 8 const int maxn = 1e4+5; 9 int ans[maxn]; 10 int main() 11 { 12 scanf("%d",&t); 13 while(t--) 14 { 15 priority_queue<int,vector<int>,greater<int> >que1; 16 priority_queue<int,vector<int>,less<int> >que2; 17 18 scanf("%d%d",&cas,&n); 19 printf("%d %d ",cas,n/2+1); 20 int tmp; 21 int l=0,r=0,num=0; 22 int cnt = 0; 23 for(int i=1;i<=n;i++) 24 { 25 scanf("%d",&tmp); 26 if(tmp > num) 27 { 28 que1.push(tmp); 29 r++; 30 } 31 else 32 { 33 que2.push(tmp); 34 l++; 35 } 36 if(r < l) 37 { 38 int f = que2.top(); 39 que2.pop(); 40 que1.push(f); 41 r++,l--; 42 } 43 else if(r > l + 1) 44 { 45 r--,l++; 46 int f = que1.top(); 47 que1.pop(); 48 que2.push(f); 49 } 50 num = que1.top(); 51 if(i&1) 52 { 53 ans[++cnt] = num; 54 } 55 } 56 for(int i=1;i<=cnt;i++) 57 { 58 printf("%d",ans[i]); 59 if(i != cnt && i%10!=0)printf(" "); 60 else printf(" "); 61 } 62 } 63 }
链表:
链表主要是个离线处理,先将所有的数据读入,然后记录下其下标。
然后对其排序,记录下在有序序列下,原来下标的数在哪出现。
然后从n~1进行处理,因为n永远是该序列剩余的数中最后出现的,也就是说不会将该数后未输入的数进行计算。
(关于中位数下标pos的移动那,按照写法是有问题的,但是这题上适用)
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; int t; int cas,n; const int maxn = 1e4+5; struct Node { int val; int next; int pre; int index; }node[maxn]; int p[maxn]; bool cmp(Node a,Node b) { return a.val < b.val; } int ans[maxn]; int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&cas,&n); printf("%d %d ",cas,(n+1)>>1); for(int i=1;i<=n;i++) { scanf("%d",&node[i].val); node[i].index = i; } sort(node+1,node+1+n,cmp); for(int i=1;i<=n;i++) { node[i].next = i+1; node[i].pre = i-1; } node[1].pre = node[n].next = -1; for(int i=1;i<=n;i++) { p[node[i].index] = i; } int pos = (n+1)>>1; int tot = 0; int l=0,r=0; for(int i=n;i>0;i--) { if(i & 1) { if(l > r)pos = node[pos].next; else if(l < r)pos = node[pos].pre; ans[++tot] = node[pos].val; l=r=0; } if(p[i] >= pos)r++; if(p[i] <= pos)l++; if(node[p[i]].pre != -1) { node[node[p[i]].pre].next = node[p[i]].next; } if(node[p[i]].next != -1) { node[node[p[i]].next].pre = node[p[i]].pre; } } for(int i=1;i<=tot;i++) { printf("%d",ans[tot-i+1]); if(i%10 != 0 && i != tot)printf(" "); else printf(" "); } } }