博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【u119】中位数
阅读量:4560 次
发布时间:2019-06-08

本文共 3425 字,大约阅读时间需要 11 分钟。

Time Limit: 1 second

Memory Limit: 128 MB

【问题描述】

给出一个长度为N的非负整数序列A[i],对于所有1 ≤ k ≤ (N + 1) / 2,输出A[1], A[2], …, A[2k - 1]的中位数。即前1,3,5,……个数的中位数。


【输入格式】

输入文件median.in的第1行为一个正整数N,表示了序列长度。 第2行包含N个非负整数A[i] (A[i] ≤ 10^9)。

【输出格式】

输出文件median.out包含(N + 1) / 2行,第i行为A[1], A[2], …, A[2i – 1]的中位数。

【数据规模】

对于20%的数据,N ≤ 100; 对于40%的数据,N ≤ 3000; 对于100%的数据,N ≤ 100000。

Sample Input1

71 3 5 7 9 11 6

Sample Output1

135

6

【题解】

维护一个大根堆和一个小根堆。

一开始把第一二元素加入到大根堆的第一个位置。然后直接输出第一个元素。

对于之后输入的元素。进行判断。如果大于大根堆的根,则放到小根堆。小于或等于则放到大根堆。

然后放完之后。进行一次判断。看一下这两个堆它们的差的绝对值是否会大于2.如果大于2的话。就把数字

多的那个堆中的根放到另外一个堆中。这样的判断也做完之后。就可以输出中位数了。比如当前i=3,则中

位数的位置就在2,先判断一下2是否等于大根堆的大小,如果是就输出大根堆的根,否则输出小根堆的根。

难点的话在堆的操作上。多熟悉就懂了。

【代码】

#include 
int dagendui[100001],xiaogendui[100001],n,pos; //拼音分别对应了大根堆和小根堆 void up_tiaozheng(int a[100001],int p,int what) //往上调整。 what对应了a堆是什么堆 { //0为大根堆 1为小根堆 int x = a[p]; //获取需要调整的数字 int i = p,j = p/2; //往上调整 所以是除2表示指向其父亲节点 //printf("p=%d\n",p); while (j > 0) //如果没有越过树的范围 { if (what ==0) //大根堆 的调整方法 { if (x > a[j]) //如果这个值比父亲节点大。那么就不符合大根堆的定义了。 { //往上走 a[i] = a[j]; i = j; j = i/2; } else //否则就找到了一个合适的位置 直接结束即可。 break; } else //小根堆 { if (x
a[j]) //大根堆往下调整的话,儿子要找大的。 j++; if (x < a[j]) { a[i] = a[j]; i = j; j = i*2; } else break; } else //小根堆 { if (j < a[0] && a[j+1] < a[j]) //小根堆要调整则要找小的。 j++; if (x > a[j]) { a[i] = a[j]; i = j; j = i*2; } else break; } } a[i] = x;}void input_data(){ scanf("%d",&n); scanf("%d",&dagendui[1]); //先把第一个元素放到大根堆的根节点。 dagendui[0] = 1; printf("%d\n",dagendui[1]); for (int i = 2;i <= n;i++) { int dd; scanf("%d",&dd);//输入的数据和大根堆的根节点比较 if (dd > dagendui[1]) //根据比较的结果放到大根堆或小根堆。 { xiaogendui[0]++; xiaogendui[xiaogendui[0]]=dd; up_tiaozheng(xiaogendui,xiaogendui[0],1); //放到末尾要先向上调整再向下调整 down_tiaozheng(xiaogendui,pos,1); } else { dagendui[0]++; dagendui[dagendui[0]] = dd; up_tiaozheng(dagendui,dagendui[0],0); down_tiaozheng(dagendui,pos,0); //同理 } if (dagendui[0] > xiaogendui[0]) //如果它们的大小之差的绝对值大于2则需要调整 { if ((dagendui[0] - xiaogendui[0]) > 2) //大根堆数字比较多 { //就把大根堆的根节点放到小根堆中去 xiaogendui[0]++; xiaogendui[xiaogendui[0]] = dagendui[1]; up_tiaozheng(xiaogendui,xiaogendui[0],1); down_tiaozheng(xiaogendui,pos,1); dagendui[1] = dagendui[dagendui[0]]; dagendui[0]--; down_tiaozheng(dagendui,1,0); } } else if (dagendui[0] < xiaogendui[0]) { if ((xiaogendui[0]-dagendui[0]) > 2) { //如果小根堆中的数字更多。则把小根堆的根节点放到大根堆中去。 dagendui[0]++; dagendui[dagendui[0]] = xiaogendui[1]; up_tiaozheng(dagendui,dagendui[0],0); down_tiaozheng(dagendui,pos,0); xiaogendui[1] = xiaogendui[xiaogendui[0]]; xiaogendui[0]--; down_tiaozheng(xiaogendui,1,1); } } if ( (i%2)==1) //如果是奇数 则输出大根堆的根节点或小根堆的根节点。 { int tt = (i+1)/2; if (tt ==dagendui[0]) //大根堆的大小和所需要输出的第tt个数字相同就可以直接输出根节点 printf("%d\n",dagendui[1]); else //否则的话就是放在小根堆的根节点了。 printf("%d\n",xiaogendui[1]); } } }int main(){ //freopen("F:\\rush.txt","r",stdin); input_data(); return 0; }

转载于:https://www.cnblogs.com/AWCXV/p/7632337.html

你可能感兴趣的文章
HDFS写流程
查看>>
使用命令wsimport构建WebService客户端[转]
查看>>
第八遍:链接详解
查看>>
Qt5.5 使用smtp发邮件的各种坑
查看>>
js奇葩错误 字符串传递问题
查看>>
人之初,性本恶
查看>>
springboot 端口号
查看>>
使用AChartEngine画动态曲线图
查看>>
安卓项目五子棋代码详解(四)
查看>>
urllib 学习一
查看>>
bzoj4196 [Noi2015]软件包管理器——树链剖分
查看>>
kafka源码阅读环境搭建
查看>>
UI设计
查看>>
androidtab
查看>>
php 事件驱动 消息机制 共享内存
查看>>
剑指offer 二叉树的bfs
查看>>
LeetCode Maximum Subarray
查看>>
让我们再聊聊浏览器资源加载优化
查看>>
underscore demo
查看>>
CSS hack
查看>>