poj 2104 K-th Number(可持久化线段树)
2012-10-25 13:39
411 查看
http://poj.org/problem?id=2104
这是我第二次写这题了,原因只前两天看了可持久化数据结构的论文,看到线段树用可持久化的方式来写可以完成这题,于是在我构思好以后就一气呵成的把这题打了出来。一打出来就顺利通过了编译,不过刚开始的时候忘记将新建的结点的两个指针都赋值,所以稍稍debug了一下这个小问题。交上去以后RE了几次,原因是我的hash写烂了。在我改过来以后又变成TLE了,于是我就改成了模拟分配内存。。。。。几经周折,终于AC了!
这个题感觉如果是用可持久化来写,思路比较容易理清,不用像划分树复杂的位置运算,也不用像树套树那样动则200行代码。
代码如下:
View Code
——written by Lyon
这是我第二次写这题了,原因只前两天看了可持久化数据结构的论文,看到线段树用可持久化的方式来写可以完成这题,于是在我构思好以后就一气呵成的把这题打了出来。一打出来就顺利通过了编译,不过刚开始的时候忘记将新建的结点的两个指针都赋值,所以稍稍debug了一下这个小问题。交上去以后RE了几次,原因是我的hash写烂了。在我改过来以后又变成TLE了,于是我就改成了模拟分配内存。。。。。几经周折,终于AC了!
这个题感觉如果是用可持久化来写,思路比较容易理清,不用像划分树复杂的位置运算,也不用像树套树那样动则200行代码。
代码如下:
View Code
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <cassert> using namespace std; const int maxn = 100005; const int HASH = 0x55555555; const int hashSize = 400009; int hash[hashSize], hashPos[hashSize]; void initHash() { memset(hashPos, -1, sizeof(hashPos)); } void insHash(int x, int pos) { int p = (x ^ HASH) % hashSize; if (p < 0) p += hashSize; while (hash[p] != x && ~hashPos[p]) { p = (p + 1) % hashSize; } hash[p] = x; hashPos[p] = pos; } int getPos(int x) { int p = (x ^ HASH) % hashSize; if (p < 0) p += hashSize; while (hash[p] != x && ~hashPos[p]) { p = (p + 1) % hashSize; } return hashPos[p]; } int buf[maxn], num[maxn]; int cntNode; struct Node { int cnt; // Node *left, *right; int left, right; Node(int _cnt = 0) { cnt = _cnt; // left = right = NULL; left = right = 0; } //} *Root[maxn], *Null; } node[maxn << 5]; int Root[maxn]; void input(int n) { memset(Root, 0, sizeof(Root)); cntNode = 0; // Null = new Node(); node[0] = Node(); for (int i = 1; i <= n; i++) { scanf("%d", &buf[i]); num[i] = buf[i]; } sort(num + 1, num + n + 1); initHash(); for (int i = 1; i <= n; i++) { insHash(num[i], i); } } //void up(Node *rt) { void up(int rt) { // rt->cnt = rt->left->cnt + rt->right->cnt; node[rt].cnt = node[node[rt].left].cnt + node[node[rt].right].cnt; } //#define lson l, m, rt->left //#define rson m + 1, r, rt->right #define lson l, m, node[rt].left #define rson m + 1, r, node[rt].right //void build(int l, int r, Node *&rt) { void build(int l, int r, int &rt) { // rt = new Node(); rt = ++cntNode; node[rt] = Node(); if (l == r) { // rt->left = rt->right = Null; return ; } int m = (l + r) >> 1; build(lson); build(rson); up(rt); } //void update(int x, int l, int r, Node *rt, Node *&newRt) { void update(int x, int l, int r, int rt, int &newRt) { if (l == r) { // newRt = new Node(rt->cnt + 1); newRt = ++cntNode; node[newRt] = Node(node[rt].cnt + 1); // newRt->left =newRt->right = Null; return ; } int m = (l + r) >> 1; // newRt = new Node(); newRt = ++cntNode; node[newRt] = Node(); // puts("???"); if (x <= m) { // update(x, lson, newRt->left); // newRt->right = rt->right; update(x, lson, node[newRt].left); node[newRt].right = node[rt].right; } else { // update(x, rson, newRt->right); // newRt->left = rt->left; update(x, rson, node[newRt].right); node[newRt].left = node[rt].left; } up(newRt); } //#define l2son l, m, rt1->left, rt2->left //#define r2son m + 1, r, rt1->right, rt2->right #define l2son l, m, node[rt1].left, node[rt2].left #define r2son m + 1, r, node[rt1].right, node[rt2].right //int query(int k, int l, int r, Node *rt1, Node *rt2) { int query(int k, int l, int r, int rt1, int rt2) { if (l == r) { return num[l]; } int m = (l + r) >> 1; // int cnt = rt2->left->cnt - rt1->left->cnt; int cnt = node[node[rt2].left].cnt - node[node[rt1].left].cnt; // assert(0 <= cnt && cnt <= r - l + 1); if (k <= cnt) { return query(k, l2son); } else { return query(k - cnt, r2son); } } int segK(int l, int r, int k, int n) { return query(k, 1, n, Root[l - 1], Root[r]); } /* void printTree(Node *rt) { if (!rt) return ; putchar('('); printTree(rt->left); printf("%d", rt->cnt); printTree(rt->right); putchar(')'); } */ int main() { int n, m; // freopen("in", "r", stdin); while (~scanf("%d%d", &n, &m)) { input(n); build(1, n, Root[0]); for (int i = 1; i <= n; i++) { update(getPos(buf[i]), 1, n, Root[i - 1], Root[i]); // printTree(Root[i]); // puts("~~~"); } while (m--) { int l, r, k; scanf("%d%d%d", &l, &r, &k); printf("%d\n", segK(l, r, k, n)); } } return 0; }
——written by Lyon
相关文章推荐
- POJ 2104 K-th Number(可持久化线段树)
- poj-2104 K-th Number[主席树/函数式线段树/可持久化线段树]
- POJ 2104 K-th Number 可持久化线段树
- 主席树(可持久化线段树)讲解 [POJ 2104] K-th Number
- POJ 2104 K-th Number (可持久化线段树)
- poj2104 K-th Number 离散+可持久化线段树
- POJ 2104 K-th Number(可持久化线段树-求第K大)
- [poj]-2104-K-th Number-可持久化线段树
- POJ 2104 K-th Number (可持久化线段树)
- POJ_2104_K-th Number_线段树(归并树)
- POJ-2104 K-th Number(线段树[归并树]-区间第k大)
- poj 2104 K-th Number 函数式线段树
- POJ 2104 kth number 主席树(可持久化线段树)[指针实现]
- [POJ 2104]K-th Number (不带修改的区间k大,函数式线段树)
- poj 2104 可持久化线段树 区间K大 不修改
- 用线段树求区间第K大(POJ 2104 K-th Number)
- [POJ]2104 K-th Number 主席树&线段树合并&整体二分
- 【原】 POJ 2104 K-th Number 线段树 划分树 合并树 解题报告
- poj 2104 K-th Number(线段树)
- 【可持久化线段树】poj 2104 静态区间第k大