POJ3784 Running Median

 

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1670 Accepted: 823

Description

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

Source

对于每个奇数次读入,输出当前已有序列的中位数

 

维护两个堆,一个大根堆,一个小根堆。大根堆里存较小的数,小根堆里存较大的数。维护好以后,小根堆顶就是中位数。

每次新加入一个数,若该数比中位数大,存入小根堆,否则存入大根堆。

限制小根堆里的数最多比大根堆大1,若不满足,就把小根堆的堆顶弹到大根堆。

 

以下是代码,基本是抄的233。

结构体里写的是小根堆,为了缩减代码长度,把大根堆取负,也按照小根堆的算法算,就能维护出大根堆。

注意输出格式。mod20==19是为了输出10个中位数就换一行。

 

 1 /*by SilverN*/
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 using namespace std;
 8 const int mxn=5000;
 9 struct pile{
10     int h[6000];
11     int cnt;
12     void insert(int x){//插入 
13         h[++cnt]=x;
14         int k=cnt;
15         while(k>1 && h[k]<h[k>>1]){//维护 
16             swap(h[k],h[k>>1]);
17             k>>=1;
18         }
19     }
20     void pop(){
21         int k=2;
22         h[1]=h[cnt];//把末尾元素顶上来 
23         h[cnt--]=0;
24         while(k<=cnt){
25             if(h[k]>h[k+1] && k<cnt)k++;//在两个子节点中找较小的 
26             if(h[k]<h[k>>1])swap(h[k],h[k>>1]),k<<=1;//把较小的顶上去 
27             else break;//满足性质,退出 
28         }
29     }
30 }big,small,empty;
31 void ins(int x){
32     if(x<=-big.h[1])
33         big.insert(-x);
34     else small.insert(x);
35     while(small.cnt>big.cnt) big.insert(-small.h[1]),small.pop();
36     while(big.cnt>small.cnt+1) small.insert(-big.h[1]),big.pop();
37 }
38 int n,m;
39 int main(){
40     int T;
41     scanf("%d",&T);
42     int i,j;
43     while(T--){
44         big=small=empty;//初始化 
45         scanf("%d%d",&n,&m);
46         int num;
47         printf("%d %d\n",n,(m+1)>>1);
48         for(i=1;i<=m;i++){
49             scanf("%d",&num);
50             ins(num);
51             if(i&1){//奇数
52                 printf("%d",-big.h[1]);
53                 if(i==m)printf("\n");else printf(" ");
54                 if(i%20==19)printf("\n");
55             }
56         }
57     }
58     return 0;
59 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/5651805.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,这是一个关于二叉树遍历的问题。具体来说,给定二叉树的前序遍历和中序遍历,需要求出二叉树的后序遍历。 以下是一个Java实现的例子: ```java import java.util.Scanner; class Node { char value; Node left; Node right; public Node(char value) { this.value = value; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int t = scanner.nextInt(); while (t-- > 0) { int n = scanner.nextInt(); String preOrder = scanner.next(); String inOrder = scanner.next(); Node root = buildTree(preOrder, inOrder); postOrder(root); System.out.println(); } scanner.close(); } private static Node buildTree(String preOrder, String inOrder) { if (preOrder.length() == 0) { return null; } char rootValue = preOrder.charAt(0); int rootIndex = inOrder.indexOf(rootValue); Node root = new Node(rootValue); root.left = buildTree(preOrder.substring(1, rootIndex + 1), inOrder.substring(0, rootIndex)); root.right = buildTree(preOrder.substring(rootIndex + 1), inOrder.substring(rootIndex + 1)); return root; } private static void postOrder(Node root) { if (root == null) { return; } postOrder(root.left); postOrder(root.right); System.out.print(root.value); } } ``` 这段代码首先读取输入的测试用例数量t,然后依次读取每个测试用例的节点数量n、前序遍历和中序遍历的字符串。接下来,通过递归构建二叉树,并使用后序遍历输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值