poj 2104 区间第k大 主席树
2015-08-05 20:25
435 查看
/* 静态主席树求区间第K大 poj 2104 主要思想: 1. 将数据离散化 2. 用线段树来维护信息,维护处于该区间的数的个数 3. 将原有数组中的每一个数依次插入,每次插入一个值的时候新建一棵线段树 这样就有了n+1棵线段树,对于询问(l,r,k),只需查询T[l-1]和T[r]两棵线段树即可,其中T[i]为插入 第i个数后的线段树询问过程,只要利用二分思想:若这两棵线段树的左儿子区间的数的个数差不小于k, 则答案往左儿树中找,否则往右子树找。 4. 上述建树空间复杂度肯定太大,所以要空间重用。 注意当插入一个数的时候,插入后的线段树(新)和插入前的线段树(旧)之间有很多信息都是一样的, 容易发现只有从修改位置到根的log(n)的路径是不一样的,所以新树中的其他不变的子树只要重用旧子树 的相应位置就好,这样每次建树空间复杂度为log(n)了。 5. 详细见代码 */ #include <cstdio> #include <algorithm> #define m (l+r)/2 using namespace std; const int N = 100100; const int M = N * 30; int n, q, num, a , b , l, r, k; int T[M], cnt[M], lson[M], rson[M], tot; int hash(int a){ return lower_bound(b + 1, b + num + 1, a) - b; } int init(int l, int r){ int root = tot ++; cnt[root] = 0; if(l < r) lson[root] = init(l, m), rson[root] = init(m + 1, r); return root; } int upd(int pre_root, int pos, int val){ int cur_root = tot ++, ret = cur_root; cnt[cur_root] = cnt[pre_root] + val; int l = 1, r = num; while(r > l){ if(pos <= m){ rson[cur_root] = rson[pre_root]; cur_root = lson[cur_root] = tot ++; pre_root = lson[pre_root]; cnt[cur_root] = cnt[pre_root] + val; r = m; } else { lson[cur_root] = lson[pre_root]; cur_root = rson[cur_root] = tot ++; pre_root = rson[pre_root]; cnt[cur_root] = cnt[pre_root] + val; l = m + 1; } } return ret; } int query(int pre, int cur, int k){ int l = 1, r = num; while(r > l){ if(k <= cnt[lson[cur]] - cnt[lson[pre]]){ pre = lson[pre]; cur = lson[cur]; r = m; } else { k -= cnt[lson[cur]] - cnt[lson[pre]]; pre = rson[pre]; cur = rson[cur]; l = m + 1; } } return l&r; } int main(){ while(~scanf("%d %d", &n, &q)){ for(int i = 1; i <= n; i ++) scanf("%d",&a[i]), b[i] = a[i]; sort(b + 1, b + n + 1); num = unique(b + 1, b + n + 1) - b - 1; tot = 0; T[0] = init(1, num); for(int i = 1; i <= n; i ++) T[i] = upd(T[i-1], hash(a[i]), 1); while(q --){ scanf("%d %d %d", &l, &r, &k); printf("%d\n", b[query(T[l - 1], T[r], k)]); } } }
相关文章推荐
- mybatis 一对一的映射(两种方式)
- NSNotification、delegate和KVO的区别
- PHP应用API接口实现
- C++ 虚函数实现原理
- iOS:hidesBottomBarWhenPushed的正确用法
- nyoj35表达式求值
- 【JAVA基础】JAVA中分包的规范
- Ubuntu14.04安装NVIDIA显卡驱动
- poj1321(深搜)
- zoj 2734 Exchange Cards
- Android studio 取消language injection
- nginx 进行外网地址屏蔽
- 【华为oj】提取不重复的整数
- xml实现rss订阅
- C#操作SQLite数据库帮助类——SQLiteHelper
- 电容标识
- hdoj 1379 DNA Sorting【排序】
- 新浪微博简记
- php调用SQL SERVER 2008及以上版本的方法
- 读书笔记--大话设计模式