hdu 4251 划分树入门题
2015-07-27 10:09
381 查看
题意:
给n个数字的数组,m个操作,操作输入fr,to。
每次操作求fr,to范围内的中位数。
解析:
把求区间的第k大数转换成了中位数。
中位数是 第 ((to - fr) >> 1) + 1 大数。
代码:
给n个数字的数组,m个操作,操作输入fr,to。
每次操作求fr,to范围内的中位数。
解析:
把求区间的第k大数转换成了中位数。
中位数是 第 ((to - fr) >> 1) + 1 大数。
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cstring> #include <cmath> #include <stack> #include <vector> #include <queue> #include <map> #include <set> #include <climits> #include <cassert> #define LL long long #define lson lo, mi, rt << 1 #define rson mi + 1, hi, rt << 1 | 1 using namespace std; const int maxn = 1e5 + 10; const int inf = 0x3f3f3f3f; const double eps = 1e-8; const double pi = acos(-1.0); const double ee = exp(1.0); int tree[30][maxn]; //表示每层每个位置的值 int sorted[maxn]; //排完序的数 int toleft[30][maxn]; //toleft[p][i]表示第p层从1到i有多少个数在左边 void build(int l, int r, int dep) { if (l == r) return; int mi = (l + r) >> 1; int same = mi - l + 1; //等于中位数的数字个数 for (int i = l; i <= r; i++) { if (tree[dep][i] < sorted[mi]) { same--; } } int lpos = l; int rpos = mi + 1; for (int i = l; i <= r; i++) { if (tree[dep][i] < sorted[mi])//比中位数小 { tree[dep + 1][lpos++] = tree[dep][i]; } else if (tree[dep][i] == sorted[mi] && same > 0) { tree[dep + 1][lpos++] = tree[dep][i]; same--; } else //比中位数大 { tree[dep + 1][rpos++] = tree[dep][i]; } toleft[dep][i] = toleft[dep][l - 1] + lpos - l; // - l 不是减一 } build(l, mi, dep + 1); build(mi + 1, r, dep + 1); } //查询区间第k大数 int query(int L, int R, int l, int r, int dep, int k) { if (l == r) return tree[dep][l]; int mi = (L + R) >> 1; int cnt = toleft[dep][r] - toleft[dep][l - 1]; if (k <= cnt) { int nextl = L + toleft[dep][l - 1] - toleft[dep][L - 1]; int nextr = nextl + cnt - 1; return query(L, mi, nextl, nextr, dep + 1, k); } else { int nextr = r + toleft[dep][R] - toleft[dep][r]; int nextl = nextr - (r - l - cnt); return query(mi + 1, R, nextl, nextr, dep + 1, k - cnt); } } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); #endif // LOCAL int n, m; int ca = 1; while (~scanf("%d", &n)) { memset(tree, 0, sizeof(tree)); memset(toleft, 0, sizeof(toleft)); for (int i = 1; i <= n; i++)//start from 1 { scanf("%d", &tree[0][i]); sorted[i] = tree[0][i]; } sort(sorted + 1, sorted + n + 1); build(1, n, 0); scanf("%d", &m); printf("Case %d:\n", ca++); while (m--) { int fr, to; scanf("%d%d", &fr, &to); printf("%d\n", query(1, n, fr, to, 0, ((to - fr) >> 1) + 1)); } } return 0; }
相关文章推荐
- Android控件开发之RatingBar
- Objective-C——Protocol
- uva 11538 计数原理
- JavaScript判断IE版本
- dedecms sql 替换 或 删除
- AHK 语句 FileSelectFile 使用选项“S16”时需注意的问题
- 2.17-switch练习
- 3.01-while
- mysql的InnoDB参数详解
- linux input子系统(一)
- Android唤醒锁问题
- Android控件开发之ImageView
- Android控件开发之CheckBox
- contentType,charset和pageEncoding的区别
- 【HDU 5305】Friends 多校第二场(双向DFS)
- 设计模式之-----观察者模式
- 最大流模板
- ASP.NET MVC异常处理
- ASP.NET POST XML JSON数据,发送与接收
- android/IOS各平台分享链接/跳转链接配置说明(备用)