[hdu2665 Kth number]区间第k大数
来源:互联网 发布:淘宝超市加盟 编辑:程序博客网 时间:2024/05/29 03:28
题意:给n个数,m次询问(l, r, k),每次询问区间[l, r]内的第k大数是多少
想法:区间问题。
* 暴力做法,将数据提取出来,然后套
* 在线段树上保存信息。比如归并树,保存归并排序的整个过程并对应到每个节点区间。或者像划分树那样,保存划分的结果,并维护一下进入到子区间的数的个数,这个信息可以在查询的时候用来确定第k大数被划到了左边还是右边。使用归并树复杂度为
* 可持久化线段树,也被称之为主席树。对每个前缀区间建一棵线段树保存数字区间的出现次数和,那么任一个区间的信息就可以由两颗线段树相减得到,然后就是在线段树上二分了。。复杂度依然是
* 如果这个题可以离线做,也可以考虑考虑莫队算法。需要用到一个支持插入、删除、求rank的数据结构,用平衡树的话复杂度为
划分树:
#include <bits/stdc++.h>using namespace std;#ifndef ONLINE_JUDGE#include "local.h"#endif // ONLINE_JUDGE#define pb(x) push_back(x)#define mp(x, y) make_pair(x, y)#define all(a) (a).begin(), (a).end()#define mset(a, x) memset(a, x, sizeof(a))#define mcpy(a, b) memcpy(a, b, sizeof(b))#define up(a, b) for (int a = 0; a < (b); a ++)#define down(a, b) for (int a = b - 1; (a) >= 0; a --)#define rep(i, a, b) for (int i = a; i <= (b); i ++)#define rrep(i, a, b) for (int i = a; i >= (b); i --)#define cas() int T, cas = 0; cin >> T; while (T --)#define printCas(ch) printf("Case #%d:%c", ++ cas, ch)#define watch(ele) cout << ele << endl;#define in(a) scanf("%d", &a)typedef long long ll;typedef pair<int, int> pii;template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}const int N = 1e5 + 7;struct SegTree { int sum[20][N], seq[20][N]; void init(int a[]) { memcpy(seq[0], a, sizeof(seq[0])); } void build(int b[], int d, int l, int r) { if (l == r) return; int m = l + r >> 1, mid = b[m], cnt = l; rep(i, l, r) if (seq[d][i] < mid) cnt ++; int tl = l, tr = m + 1; rep(i, l, r) { int val = seq[d][i]; sum[d][i] = sum[d][i - 1]; if (val < mid) seq[d + 1][tl ++] = val, sum[d][i] ++; if (val > mid) seq[d + 1][tr ++] = val; if (val == mid) { if (cnt <= m) seq[d + 1][tl ++] = val, sum[d][i] ++, cnt ++; else seq[d + 1][tr ++] = val; } } build(b, d + 1, l, m); build(b, d + 1, m + 1, r); } int query(int L, int R, int k, int d, int l, int r) { if (l == r) return seq[d][l]; int m = l + r >> 1, cr = sum[d][R] - sum[d][l - 1], cl = sum[d][L - 1] - sum[d][l - 1], buf = cr - cl; if (buf >= k) return query(l + cl, l + cr - 1, k, d + 1, l, m); else return query(m + 1 + L - l - cl, m + R - l + 1 - cr, k - buf, d + 1, m + 1, r); }};SegTree st;int n, m, s, t, k, a[N], b[N];int main() {#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout);#endif // ONLINE_JUDGE cas() { cin >> n >> m; up(i, n) in(a[i + 1]); mcpy(b, a); sort(b + 1, b + 1 + n); st.init(a); st.build(b, 0, 1, n); while (m --) { in(s); in(t); in(k); printf("%d\n", st.query(s, t, k, 0, 1, n)); } } return 0;}
主席树:
#include <bits/stdc++.h>using namespace std;#ifndef ONLINE_JUDGE#include "local.h"#endif // ONLINE_JUDGE#define pb(x) push_back(x)#define mp(x, y) make_pair(x, y)#define all(a) (a).begin(), (a).end()#define mset(a, x) memset(a, x, sizeof(a))#define mcpy(a, b) memcpy(a, b, sizeof(b))#define up(a, b) for (int a = 0; a < (b); a ++)#define down(a, b) for (int a = b - 1; (a) >= 0; a --)#define rep(i, a, b) for (int i = a; i <= (b); i ++)#define rrep(i, a, b) for (int i = a; i >= (b); i --)#define cas() int T, cas = 0; cin >> T; while (T --)#define printCas(ch) printf("Case #%d:%c", ++ cas, ch)#define watch(ele) cout << ele << endl;#define in(a) scanf("%d", &a)typedef long long ll;typedef pair<int, int> pii;template<typename T>bool umax(T&a, const T&b){return a<b?(a=b,true):false;}template<typename T>bool umin(T&a, const T&b){return b<a?(a=b,true):false;}const int N = 1e5 + 7;struct SegTree { struct Node { int lp, rp, sum; }; int c; Node node[N * 22]; void clear() { c = 0; mset(node, 0); } void build(int l, int r, int &rt) { rt = c ++; if (l == r) return; int m = l + r >> 1; build(l, m, node[rt].lp); build(m + 1, r, node[rt].rp); } void update(int x, int v, int last, int l, int r, int &rt) { rt = c ++; node[rt] = node[last]; node[rt].sum += v; if (l == r) return; int m = l + r >> 1; if (x <= m) update(x, v, node[last].lp, l, m, node[rt].lp); else update(x, v, node[last].rp, m + 1, r, node[rt].rp); } int query(int s, int t, int k, int l, int r) { if (l == r) return l; int m = l + r >> 1, buf = node[node[t].lp].sum - node[node[s].lp].sum; if (buf >= k) return query(node[s].lp, node[t].lp, k, l, m); else return query(node[s].rp, node[t].rp, k - buf, m + 1, r); }};SegTree st;int n, m, s, t, k, sz, a[N], b[N], root[N];int main() {#ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout);#endif // ONLINE_JUDGE cas() { cin >> n >> m; up(i, n) in(a[i]); up(i, n) b[i] = a[i]; sort(b, b + n); sz = unique(b, b + n) - b; up(i, n) a[i] = lower_bound(b, b + sz, a[i]) - b; st.clear(); st.build(0, sz - 1, root[0]); up(i, n) st.update(a[i], 1, root[i], 0, sz - 1, root[i + 1]); while (m --) { in(s); in(t); in(k); printf("%d\n", b[st.query(root[s - 1], root[t], k, 0, sz - 1)]); } } return 0;}
0 0
- [hdu2665 Kth number]区间第k大数
- HDU2665 Kth number(区间第K大)
- hdu2665-Kth number
- HDU2665-Kth number
- HDU2665 Kth number
- Find the Kth number(找第K大数)
- HDU 2665 Kth number(区间第K大)
- 区间第K大数
- 区间第K大数
- HDU2665 Kth number 【归并树】
- 主席树 hdu2665 Kth number
- HDU2665(函数式线段树-区间第K大)
- 主席树模板(区间第k大!)hdu2665
- hdu2665区间第K大+主席树解题报告
- HDU 4006 The kth great number 【优先队列求第K大数】
- HDU 4006 The kth great number(优先队列·第K大数)
- POJ 2104K-th Number&&HDU 2665Kth number划分树 求区间第k大 裸题
- 静态区间第k大数
- Scroll滑动效果
- Hibernate框架学习(搭建)
- lua table 计算长度
- [android]_[绘图]
- POJ 1151(线段树+扫描线)
- [hdu2665 Kth number]区间第k大数
- 稀疏问题的学习2
- 精彩美文
- 数组类型基础
- OpenCV学习资料(PNG格式处理)
- C# 中的异常捕捉(try)和异常处理(catch)
- Android viewpager+fragment实现动态加载碎片(fragment重复使用)
- C#实现电影院购票管理系统
- JVM垃圾回收示例