poj3784 Running Median 题解报告(对顶堆)

题目传送门

【题目大意】

读入一个整数序列,每当已经读入的整数个数为奇数时,输出已经读入的整数构成的序列的中位数。

【思路分析】

这题可以使用“对顶堆”的在线做法。为了动态维护中位数,我们可以建立两个二叉堆,一个小根堆、一个大根堆。在以此读入序列的过程中,设当前读入的序列长度为$L$,我们始终保持:

1.序列中从小到大排名为$1~\frac{M}{2}$的整数储存在大根堆中

2.序列中从小到到排名为$\frac{M}{2}+1~M$的整数储存在小根堆中

任何时候,如果某一个堆中元素过多,打破了这个性质,就取出该堆的堆顶插入另一个堆。这样就能保证序列的中位数为小根堆的堆顶。

重新读入一个整数$X$时,如果$X$小于当前的中位数,就插入大根堆,否则插入小根堆,在插入后检查并维护上述性质即可,这就是“对顶堆”算法。

【代码实现】

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #define rg register
 5 #define go(i,a,b) for(rg int i=a;i<=b;i++)
 6 using namespace std;
 7 int T,m,n,mid;
 8 priority_queue<int>q1;//小根堆
 9 priority_queue<int,vector<int>,greater<int> >q2;//大根堆
10 int main(){
11     scanf("%d",&T);
12     while(T--){
13         scanf("%d%d",&m,&n);printf("%d %d\n",m,n/2+1);
14         while(q1.size()>0) q1.pop();
15         while(q2.size()>0) q2.pop();
16         go(i,1,n){
17             int x;scanf("%d",&x);
18             if(i==1){mid=x;q2.push(x);}
19             else{
20                 if(x<mid)q1.push(x);
21                 else q2.push(x);
22             }
23             while((int)q1.size()-(int)q2.size()>1){int y=q1.top();q1.pop();q2.push(y);}
24             while((int)q2.size()>(int)q1.size()){int y=q2.top();q2.pop();q1.push(y);}
25             mid=q1.top();
26             if(i&1) printf("%d ",mid);
27             if((i&1)&&(i/2+1)%10==0) puts("");
28         }
29         if((m/2+1)%10) puts("");
30     }
31     return 0;
32 }
代码戳这里

转载于:https://www.cnblogs.com/THWZF/p/11248741.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、付费专栏及课程。

余额充值