hdu 2852 KiKi's K-Number(BIT, 线段树,treap)
2014-12-08 23:48
357 查看
题意:
一个集合,初始为空。
三种操作,插入一个元素,删除一个元素,查询集合中大于a的第k个数。
解法一:
如果用 x[i] 记录 i 在集合中的个数,则可用BIT或segment tree解决。
解法二:
既然是名次问题,当然可以用treap解决。
这次又更新了我的treap模板 = =
原来的写法 在处理元素可重的情况 时,为每个重复的元素都建一个节点,因为右子树的元素大于等于根,所以在极端情况下会退化。
后来为每个节点加上count属性,表示该元素重复的个数,解决了这个问题~~~^_^
参考:
http://www.nocow.cn/index.php/Treap_C%2B%2B
下面是code
一个集合,初始为空。
三种操作,插入一个元素,删除一个元素,查询集合中大于a的第k个数。
解法一:
如果用 x[i] 记录 i 在集合中的个数,则可用BIT或segment tree解决。
解法二:
既然是名次问题,当然可以用treap解决。
这次又更新了我的treap模板 = =
原来的写法 在处理元素可重的情况 时,为每个重复的元素都建一个节点,因为右子树的元素大于等于根,所以在极端情况下会退化。
后来为每个节点加上count属性,表示该元素重复的个数,解决了这个问题~~~^_^
参考:
http://www.nocow.cn/index.php/Treap_C%2B%2B
下面是code
#include <cmath> #include <cstdio> #include <cstdlib> #include <climits> #include <string> #include <vector> #include <queue> #include <iostream> #include <algorithm> #include <map> #include <set> using namespace std; #define rep(i, s, t) for(int (i)=(s);(i)<=(t);++(i)) #define urep(i, s, t) for(int (i)=(s);(i)>=(t);--(i)) const int inf = 0x7fffffff; const int Maxn = 100000; typedef long long LL; const double eps = 1e-10; //#define DEBUG int rankArr[Maxn+5]; typedef struct Node { Node *ch[2]; int r; // rank int v; // value int s; // size 名次树中子树结点个数 int cnt; // 有多少个相同的节点 int cmp(int x) const { if (x == v) return -1; return x < v ? 0 : 1; } void maintain() { s = cnt; if (ch[0] != NULL) s += ch[0]->s; if (ch[1] != NULL) s += ch[1]->s; } }TreapNode; class Treap { public: int find(TreapNode* o, int x) { while (o != NULL) { int d = o->cmp(x); if (d == -1) return 1; // find else o = o->ch[d]; } return 0; // not find } // 返回小于等于x的数的个数 int rank(TreapNode* o, int x) { int ret = 0; while (o != NULL) { int d = o->cmp(x); if (d == 0) { o = o->ch[0]; } else { if (o->ch[0] != NULL) ret += o->ch[0]->s + o->cnt; else ret += o->cnt; o = o->ch[1]; } } return ret; // not find } void insert(TreapNode* &o, int x) { if (o == NULL) { //o = new TreapNode(); //o->ch[0] = o->ch[1] = NULL; //o->v = x; //o->r = rand(); //o->s = 1; make_node(o, x); } else { #ifdef DEBUG cout << "d: " << "fa: " << o->v << " son: " << x << endl; #endif // DEBUG int d = o->cmp(x); if (d == -1) { o->cnt += 1; #ifdef DEBUG cout << "d: " << x << " add 1" << endl; #endif // DEBUG o->maintain(); return; } insert(o->ch[d], x); if (o->ch[d]->r > o->r) { #ifdef DEBUG cout << "rotate: " << "fa: " << (o->v) << " son: " << (o->ch[d]->v) << " di: " << (d^1) << endl; #endif // DEBUG rotate(o, d^1); } } o->maintain(); } // 两棵子树:先把优先级较高的旋转到根 // 然后在另一棵子树中递归删除x void remove(TreapNode* &o, int x) { int d = o->cmp(x); if (d == -1) { if (o->cnt > 0) o->cnt -= 1; if (o->cnt == 0) { TreapNode* u = o; if (o->ch[0] == NULL) { o = o->ch[1]; delete u; } else if (o->ch[1] == NULL) { o = o->ch[0]; delete u; } else { if (o->ch[0]->r > o->ch[1]->r) { d = 1; } else { d = 0; } rotate(o, d); remove(o->ch[d], x); } } } else { remove(o->ch[d], x); } if(o != NULL) o->maintain(); } // 求第k大的值 0表示不存在 int kth(TreapNode* o, int k) { if (o == NULL || k <= 0 || k > o->s) return 0; int s = o->ch[1] == NULL ? 0 : o->ch[1]->s; if (s+1 <= k && k <= s+o->cnt) return o->v; else if (k <= s) return kth(o->ch[1], k); else return kth(o->ch[0], k-s-o->cnt); } void mergeto(TreapNode* &src, TreapNode* &dst) { if (src->ch[0] != NULL) mergeto(src->ch[0], dst); if (src->ch[1] != NULL) mergeto(src->ch[1], dst); insert(dst, src->v); delete src; src = NULL; } void make_node(TreapNode* &o, int x) { o = new TreapNode(); o->ch[0] = o->ch[1] = NULL; //o->r = rand(); // 直接调用 rand() o->r = rankArr[x]; // 使用事先分配好的rank o->s = 1; o->v = x; o->cnt = 1; #ifdef DEBUG cout << "new: " << " r: " << o->r << " v: " << o->v << " s: " << o->s << endl; #endif // DEBUG } void destroy(TreapNode* &o) { if (o == NULL) return; if (o->ch[0] != NULL) destroy(o->ch[0]); if (o->ch[1] != NULL) destroy(o->ch[1]); delete o; o = NULL; } private: // 旋转操作:d=0左转 d=1右转 void rotate(TreapNode* &o, int d) { TreapNode* k = o->ch[d^1];o->ch[d^1] = k->ch[d];k->ch[d] = o; // o成为k的子树 而k的另一个子树没发生变化 // 所以先维护o 在维护k o->maintain(); k->maintain(); o = k; } }; Treap treap; TreapNode * root = NULL; int main() { #if 1 freopen("input.in", "r", stdin); #endif //iostream::sync_with_stdio(false); int t, op, x, y; rep(i, 1, Maxn) rankArr[i] = rand(); while (scanf("%d" ,&t) != EOF) { while(t--) { scanf("%d", &op); if (op == 0) { scanf("%d", &x); treap.insert(root, x); //cout << "insert: " << x << " size become: " << root->s << endl; } else if (op == 1) { scanf("%d", &x); if (treap.find(root, x) == 1) treap.remove(root, x); else puts("No Elment!"); } else if (op == 2) { scanf("%d%d", &x, &y); int Rank = treap.rank(root, x); int Rank2 = root->s - Rank - y + 1; //cout << "tot: " << root->s << " x: " << x << " rank: " << Rank << endl; int tmp; if (Rank2 >= 1 && (tmp = treap.kth(root, Rank2)) != 0) printf("%d\n", tmp); else puts("Not Find!"); } } treap.destroy(root); } return 0; }
相关文章推荐
- hdu 2852 KiKi's K-Number(线段树)
- HDU 2852 KiKi's K-Number(线段树单点更新)
- HDU 2852-KiKi's K-Number(线段树)
- hdu 2852 KiKi's K-Number(线段树单点更新)
- hdu 2852 KiKi's K-Number 二分+树状数组
- hdu 2852 KiKi's K-Number (树状数组)
- HDU 2852 KiKi's K-Number
- HDOJ 题目2852 KiKi's K-Number(线段树求大于a的第k值)
- hdu 2852 KiKi's K-Number
- 查询比a大的数中的第k大的数 树状数组 hdu 2852 KiKi's K-Number
- HDU 2852 KiKi's K-Number 主席树或树状数组
- HDU 2852 KiKi's K-Number 树状数组
- HDU 2852 KiKi's K-Number
- HDU 2852——KiKi's K-Number(树状数组+二分查找, 第k大)
- hdu 5.3.1 2852 KiKi's K-Number
- hdu2852——KiKi's K-Number
- hdu2852 KiKi's K-Number
- HDU 2852 KiKi's K-Number(动态过程求第K小数)
- hdu 2852 KiKi's K-Number(树状数组+二分)
- hdu 2852 KiKi's K-Number(树状数组)