您的位置:首页 > 大数据 > 人工智能

hdu 4251 The Famous ICPC Team Again

2012-08-12 11:21 453 查看
hdu 4251 The Famous ICPC Team Again 划分树

//hdu 4251 The Famous ICPC Team Again
//划分树

//求中位数(就是求中间大的)
//建树和查找,模板题,看代码
//不懂可以看看这人写的
//http://www.cnblogs.com/183zyz/archive/2012/08/01/2618295.html

#define infile freopen("in.txt", "r", stdin);
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define N 100005

using namespace std;

struct NODE
{
int l, r;
}tree[4*N];

int sorted
, level[20]
;//level记录每一层每个段的序列
int l_cnt[20]
;   //记录left到right中进入

void build(int left, int right, int loc, int dep)
{
tree[loc].l = left;
tree[loc].r = right;
if(left == right)
return;

int mid = left + (right-left)/2;

int mid_val = sorted[mid];

int cnt = 0;    //记录小于left到right这段的中值的个数
for(int i = left; i <= right; ++i)
if(level[dep][i] < mid_val)
cnt++;

//这里l_tot是从left开始···
int l_tot = left, r_tot = mid + 1;
int equal_cnt = 0;  //equal_cnt记录跟mid_val相等且进入左子树的个数
for(int i = left; i <= right; ++i)
{
if(level[dep][i] < mid_val) //小于mid_val的进入左子树
level[dep+1][l_tot++] = level[dep][i];
else if(level[dep][i] == mid_val && mid-left+1 - cnt > equal_cnt)
{   //等于mid_val的且没超过左子树限定个数的时候进入左子树
equal_cnt++;
level[dep+1][l_tot++] = level[dep][i];
}
else
level[dep+1][r_tot++] = level[dep][i];
l_cnt[dep][i] = l_tot - left;   //记录进入左子树的个数
}
build(left, mid, 2*loc, dep+1);
build(mid+1, right, 2*loc+1, dep+1);
}

int ans;
void find(int loc, int from, int to, int dep, int aim)
{
int left = tree[loc].l, right = tree[loc].r;
if(left == right)
{
ans = level[dep][left];
return;
}
int mid = left + (right-left)/2;

//l_from记录当前层中,from以前的数进入左子树的个数(不包括from这个数)
//l_to记录当前层中,to以前的数进入又子树的个数,包括to
int l_from, l_to = l_cnt[dep][left+to-1];
if(from > 1)
l_from = l_cnt[dep][from+left-2];
else
l_from = 0;

//接下去那层就应该保持和这层一样的起点,即from左边的个数不变
//若下一层到左子树,则要从from以左的进入左子树的个数(from_cnt)开始
//由于from这个数也到左子树所以下一层应从from_cnt+1开始
//若下一层到右子树要去掉进入左子树的个数
if(l_to - l_from >= aim)    //from到to之间进入左子树的个数
find(2*loc, l_from+1, l_to, dep+1, aim);
else
find(2*loc+1, from-1-l_from+1, to-l_to, dep+1, aim-(l_to-l_from));
}

int main()
{
//infile
int n, n_case = 1;;
while(scanf("%d", &n) != EOF)
{
printf("Case %d:\n", n_case++);
for(int i = 1; i <= n; ++i)
{
scanf("%d", &level[1][i]);
sorted[i] = level[1][i];
}
sort(sorted+1, sorted+n+1);
build(1, n, 1, 1);
int n_query;
scanf("%d", &n_query);
while(n_query--)
{
int from, to;
scanf("%d%d", &from, &to);
find(1, from, to, 1, (to-from)/2+1);
printf("%d\n", ans);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: