您的位置:首页 > 其它

POJ 3784 Running Median (动态中位数)

2015-07-17 11:01 369 查看
题目链接:http://poj.org/problem?id=3784

题目大意:依次输入n个数,每当输入奇数个数的时候,求出当前序列的中位数(排好序的中位数)。

  此题可用各种方法求解。

  排序二叉树方法,每个结点保存以其为根的左右子树中数的个数。如果数据出的够严格,这种方法会被卡的,除非是通过动态调整维持树的高度较小。

  排序二叉树的代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define N 20000

int tr[N<<2];//线段树

void insert(int id, int l, int r, int pos)//在一个位置插入
{
tr[id]++;
if(l == r) return ;
int lc = id<<1, rc = (id<<1)|1, mid = (l+r)>>1;
if(pos <= mid) insert(lc, l, mid, pos);
else insert(rc, mid+1, r, pos);
}

int query(int id, int l, int r, int c)//查询第c个数
{
if(l == r) return l;
int lc = id<<1, rc = (id<<1)|1, mid = (l+r)>>1;
if(tr[lc] >= c) return query(lc, l, mid, c);
else return query(rc, mid+1, r, c-tr[lc]);
}

int ans
;
int sq
, sortsq
;

int find(int l, int r, int v)
{
while(l <= r)
{
int mid = (l+r)>>1;
if(v == sortsq[mid]) return mid;
else if(v < sortsq[mid]) r = mid-1;
else l = mid+1;
}
}

int main()
{
int T, cas, n, v;
scanf("%d", &T);
while(T--)
{
memset(tr, 0, sizeof(tr));
int c = 0;
scanf("%d %d", &cas, &n);
for(int i = 0; i < n; i++) scanf("%d", &sq[i]);
memcpy(sortsq, sq, sizeof(sq));
sort(sortsq, sortsq+n);
//for(int i = 0; i < n; i++) printf("%d ", sortsq[i]); puts("");

for(int i = 0; i < n; i++)
{
int id = find(0, n-1, sq[i]);
insert(1, 0, n-1, id);
if(i%2 == 0)
//printf("id = %d\n", query(1, 0, n-1, (i+2)/2));
ans[c++] = sortsq[query(1, 0, n-1, (i+2)/2)];
}
//for(int i = 1; i <= 2*n; i++)printf("%d ", tr[i]); puts("");
printf("%d %d\n", cas, (n+1)/2);
printf("%d",ans[0]);
for(int i = 1; i < c; i++)
{
if(i%10==0)puts("");
else printf(" ");
printf("%d", ans[i]);
}
if(c % 10 != 0) puts("");

}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: