主席树几道题目
来源:互联网 发布:贾米森数据 编辑:程序博客网 时间:2024/05/18 03:35
主要参考cxlove博客kuangbin博客
感觉主席树和划分树有类似之处,分治的思想
Poj2104 主席树静态区间第k值
以每个位置为起点,建立一棵主席树,保存后缀区间的情况。
每个节点保存的是该后缀在相应区间数的个数
const int MAXN = 100010;const int MOD = 1000000;int a[MAXN], t[MAXN];int T[MAXN * 30], lson[MAXN * 30],rson[MAXN * 30], c[MAXN * 30];int n, sz, q;int tot;void init_hash(){ FE(i, 1, n) t[i] = a[i]; sort(t + 1, t + 1 + n); sz = unique(t + 1, t + 1 + n) - t - 1;}int build(int l, int r){ int rt = tot++; c[rt] = 0; if (l != r) { int m = (l + r) >> 1; lson[rt] = build(l, m); rson[rt] = build(m + 1, r); } return rt;} int hash(int x){ returnlower_bound(t + 1, t + 1 + n, x) - t;} int update(int rt, int pos, int val){ int new_rt = tot++; int tmp = new_rt; c[new_rt] = c[rt] + val; int l = 1, r = sz; while (l < r) { int m = (l + r) >> 1; if (pos <= m) { lson[new_rt] = tot++; rson[new_rt] = rson[rt]; new_rt = lson[new_rt]; rt = lson[rt]; r = m; } else { rson[new_rt] = tot++; lson[new_rt] = lson[rt]; new_rt = rson[new_rt]; rt = rson[rt]; l = m + 1; } c[new_rt] = c[rt] + val; } return tmp;} int query(int L, int R, int k){ int l = 1, r = sz; while (l < r) { int m = (l + r) >> 1; if (c[lson[L]] - c[lson[R]] >= k) { L = lson[L]; R = lson[R]; r = m; } else { k -= c[lson[L]] - c[lson[R]];///!!! L = rson[L]; R = rson[R]; l = m + 1; } } return l;} int main(){ int x, y, z; while (cin >> n >> q) { tot = 0; FE(i, 1, n) RI(a[i]); init_hash(); T[n + 1] = build(1, sz);///!!! FED(i, n, 1) { int pos = hash(a[i]); T[i] = update(T[i + 1], pos, 1); } while (q--) { RIII(x, y, z); printf("%d\n", t[query(T[x], T[y + 1], z)]); } }}
spoj EQUERY 静态区间,区间中不同值的数的个数
对于每一个起始位置,都建立一棵主席树
从后往前更新,更新的时候就是在next位置先减掉,然后更新在当前位置。
主席树又称为可持久化线段树,其本质上是保存了所有的历史信息。
也可以理解为多棵线段树,在更新的时候,充分共同利用历史信息
对于点更新来说,更新的总是某一棵子树,另外一棵子树,则指向原来的结点即可。
可是即使如此,主席树还是需要大量的空间。
const int MAXN = 100010;const int MOD = 1000000; int a[MAXN], t[MAXN];int T[MAXN * 60], lson[MAXN * 60],rson[MAXN * 60], c[MAXN * 60];int n, q;int tot;map<int, int> mp; int build(int l, int r){ int rt = tot++; c[rt] = 0; if (l != r) { int m = (l + r) >> 1; lson[rt] = build(l, m); rson[rt] = build(m + 1, r); } return rt;} int update(int rt, int pos, int val){ int new_rt = tot++; int tmp = new_rt; c[new_rt] = c[rt] + val; int l = 1, r = n; while (l < r) { int m = (l + r) >> 1; if (pos <= m) { lson[new_rt] = tot++; rson[new_rt] = rson[rt]; new_rt = lson[new_rt]; rt = lson[rt]; r = m; } else { rson[new_rt] = tot++; lson[new_rt] = lson[rt]; new_rt = rson[new_rt]; rt = rson[rt]; l = m + 1; } c[new_rt] = c[rt] + val; } return tmp;} int query(int rt, int pos){ int ans = 0; int l = 1, r = n; while (l < r)///(pos < r) { int m = (l + r) >> 1; if (pos <= m) { rt = lson[rt]; r = m; } else { ans += c[lson[rt]]; rt = rson[rt]; l = m + 1; } } return ans + c[rt];} int main(){ int x, y, z; while (cin >> n) { tot = 0; FE(i, 1, n) RI(a[i]); mp.clear(); T[n + 1] = build(1, n); FED(i, n, 1) { if (mp.find(a[i]) == mp.end()) { T[i] = update(T[i + 1], i, 1); } else { int tmp = update(T[i + 1],mp[a[i]], -1); T[i] = update(tmp, i, 1); } mp[a[i]] = i; } cin >> q; while (q--) { RII(x, y); printf("%d\n", query(T[x], y)); } }}
zoj 2112 Dynamic Rankings 动态第k值,树状数组套线段树
、、、
- 主席树几道题目
- 主席树经典题目 区间k大值 poj2104
- [省选前题目整理][BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- POJ 题目2761 Feed the dogs(主席树||划分树)
- 主席、树、主席树!
- 轮值主席
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- 主席树
- .Net FrameWork 4.0之WorkFlow
- 图像处理算法2——Otsu最佳阈值分割法
- mysql的查询select 语句
- SSH实现原理
- 浮点数在计算机内存中是如何存储的?
- 主席树几道题目
- “QT中QString 转const char*为乱码或为空的问题 ”之解决方案
- error C2054: 在“using”之后应输入“(”
- Linux内核移植和根文件系统制作
- 让TextView 自带滚动条
- ListCtrl 使用方法总结
- 关于Linux下面移动硬盘读不出来
- linux的内核编译和驱动安装
- linux share screen