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

HDU 4251 The Famous ICPC Team Again 划分树 区间第K大

2016-07-11 09:35 656 查看
给n个数,m次询问,每次询问一个区间,输出该区间中间大的值,中位数?划分树模版题。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100010;
int tree[20][maxn], toleft[20][maxn], a[maxn];
void build(int l, int r, int dep)
{
if(l == r)
return;
int m = (l+r) >> 1;
int tol = m-l+1;
for(int i = l; i <= r; i++)
{
if(tree[dep][i] < a[m])
tol--;
}
int L = l, R = m+1;
for(int i = l; i <= r; i++)
{
if(tree[dep][i] < a[m])
tree[dep+1][L++] = tree[dep][i];
else if(tree[dep][i] == a[m] && tol > 0)
{
tree[dep+1][L++] = tree[dep][i];
tol--;
}
else
tree[dep+1][R++] = tree[dep][i];
toleft[dep][i] = toleft[dep][l-1] + L-l;
}
build(l, m, dep+1);
build(m+1, r, dep+1);
}
int query(int L, int R, int l, int r, int dep, int k)
{
if(l == r)
return tree[dep][l];
int m = (L+R) >> 1;
int cnt = toleft[dep][r]-toleft[dep][l-1];
if(cnt >= k)
{
int nextl = L + toleft[dep][l-1]-toleft[dep][L-1];
int nextr = nextl + cnt - 1;
return query(L, m, nextl, nextr, dep+1, k);
}
else
{
int nextr = r + toleft[dep][R]-toleft[dep][r];
int nextl = nextr-(r-l-cnt);
return query(m+1, R, nextl, nextr, dep+1, k-cnt);
}

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