poj 3784 Running Median 二叉堆

传送门


题目大意:
依次添加 n 个数,要求第奇数次添加时,输出当前数列中的中位数。


分析:
维护一个大根堆一个小根堆,大的数插入小根堆,小的数插入大根堆,每次取大根堆堆顶就是中位数


代码如下:(第一次手写二叉堆,所以是抄的POPOQQQ的模板>o< >_<)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=5000+5;
int p,a,m;
struct small_root_heap{//小根堆 
    int heap[maxn],size;
    void insert(int x){
        heap[++size]=x;
        int t=size;
        while(t>1&&heap[t]<heap[t>>1])//不断向上调整直到比父结点不优为止
            swap(heap[t],heap[t>>1]),t>>=1;
    }
    void pop(){//弹顶 
        int t=2;
        heap[1]=heap[size],heap[size--]=0;
        while(t<=size){
            if(heap[t]>heap[t+1]&&t<size)
                t++;
            if(heap[t]<heap[t>>1])//不断向上调整直到比父结点不优为止
                swap(heap[t],heap[t>>1]),t<<=1;
            else
                break;
        }
    }
}topheap,bottomheap,empty;//topheap是小根堆,bottomheap是大根堆
void add(int x){
    if(x<=-bottomheap.heap[1])
        bottomheap.insert(-x);
    else
        topheap.insert(x);//小的插入大根堆,大的插入小根堆 
    //插入,保证下堆的任意元素都小于等于上堆的任意元素   
    //注意一定要和下堆堆顶比较,因为第一次插入后元素一定在下堆,如果和上堆堆顶比较就会WA 
    while(topheap.size>bottomheap.size)
        bottomheap.insert(-topheap.heap[1]),topheap.pop();
    while(bottomheap.size>topheap.size+1)
        topheap.insert(-bottomheap.heap[1]),bottomheap.pop();
    //维护上下堆平衡,保证两堆元素数相等或下堆元素数比上堆元素数多1 
} 
signed main(void){
    scanf("%d",&p);
    while(p--){
        scanf("%d%d",&a,&m);
        topheap=bottomheap=empty;
        printf("%d %d\n",a,(m+1)>>1);
        for(int i=1,x;i<=m;i++){
            scanf("%d",&x);
            add(x);
            if(i&1){
                printf("%d%c",-bottomheap.heap[1],i==m?'\n':' ');
                if(i%20==19)
                    printf("\n");
            } 
        }
    }
    return 0;
}

by >o< neighthorn

  • 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、付费专栏及课程。

余额充值