您的位置:首页 > 其它

JZOJ 2152 终极数

2018-02-01 21:43 337 查看
给定一个长度为n的序列a,试求出对于序列a的每一个前缀的终极数x,使得



最小

首先这道题比较搞事。

一开始还是一脸懵逼的

然后后来发现就是求1——i(i<=n)的中位数,这几个数的中位数

详情看代码解析

#include <cstdio>
#include <algorithm>
using namespace std;
int a[500001],b[500001],c[1000001],n,x;
void up1(int x){while (x>1&&a[x]<a[x/2]) swap(a[x],a[x/2]),x/=2;}
void up2(int x){while (x>1&&b[x]>b[x/2]) swap(b[x],b[x/2]),x/=2;}
void down1(int x){ int y;
while (x*2<=a[0]&&a[x]>a[x*2]||x*2+1<=a[0]&&a[x]>a[x*2+1]){
if (x*2+1>a[0]||a[x*2]<a[x*2+1]) y=x*2; else y=x*2+1;
swap(a[x],a[y]); x=y;}}
void down2(int x){ int y;
while (x*2<=b[0]&&b[x]<b[x*2]||x*2+1<=b[0]&&b[x]<b[x*2+1]){
if (x*2+1>b[0]||b[x*2]>b[x*2+1]) y=x*2; else y=x*2+1;
swap(b[x],b[y]); x=y;}}
int main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%d",&x);
if (i%2) a[++a[0]]=x,up1(a[0]);//先插入小根堆
else b[++b[0]]=x,up2(b[0]);//再插入大根堆
while (a[1]<b[1]) swap(a[1],b[1]),down1(1),down2(1);//小根堆的堆顶比大根堆的堆顶大就交换,并维护两个堆
c[i]=a[1];//中位数
}
sort(c+1,c+1+n); printf("%d",c[n/2]); return 0;//快排后正中间的输为中位数
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: