区间第k大 可修改主席树,树状数组套线段树。
2017-06-02 20:43
399 查看
#include <cstdio> #include <vector> using namespace std; const int N = 100010; struct Node { int cnt; Node *ls, *rs; }pool[N * 200], *tail = pool, *roots , *null; int n, q; int aa ; Node *va[10000], *vb[10000]; int ca, cb; void init() { null = ++tail; null->ls = null; null->rs = null; null->cnt = 0; } Node *newnode() { Node *nd = ++tail; nd->ls = null; nd->rs = null; nd->cnt = 0; return nd; } void modify( int lf, int rg, int pos, int delta ) { for( int t = 0; t < ca; t++ ) va[t]->cnt += delta; if( lf == rg ) return; int mid = (lf + rg)>>1; if( pos <= mid ) { for( int t = 0; t < ca; t++ ) { if( va[t]->ls == null ) va[t]->ls = newnode(); va[t] = va[t]->ls; } modify( lf, mid, pos, delta ); } else { for( int t = 0; t < ca; t++ ) { if( va[t]->rs == null ) va[t]->rs = newnode(); va[t] = va[t]->rs; } modify( mid+1, rg, pos, delta ); } } int query_seg( int lf, int rg, int k ) { if( lf == rg ) return lf; int mid = (lf + rg) >> 1; int lz = 0; for( int t = 0; t < ca; t++ ) lz += va[t]->ls->cnt; for( int t = 0; t < cb; t++ ) lz -= vb[t]->ls->cnt; if( k <= lz ) { for( int t = 0; t < ca; t++ ) va[t] = va[t]->ls; for( int t = 0; t < cb; t++ ) vb[t] = vb[t]->ls; return query_seg( lf, mid, k ); } else { for( int t = 0; t < ca; t++ ) va[t] = va[t]->rs; for( int t = 0; t < cb; t++ ) vb[t] = vb[t]->rs; k -= lz; return query_seg( mid+1, rg, k ); } } void modify( int u, int x, int delta ) { ca = 0; for( int i = u; i <= n; i += i & -i ) va[ca++] = roots[i]; modify( 1, n, x, delta ); } void modify( int u, int x ) { modify( u, aa[u], -1 ); modify( u, x, +1 ); aa[u] = x; } int query( int l, int r, int k ) { ca = cb = 0; for( int i = r; i; i -= i & -i ) va[ca++] = roots[i]; for( int i = l - 1; i; i -= i & -i ) vb[cb++] = roots[i]; return query_seg(1,n,k); } int main() { scanf( "%d%d", &n, &q ); for( int i = 1; i <= n; i++ ) scanf( "%d", aa + i ); init(); for( int i = 1; i <= n; i++ ) roots[i] = newnode(); for( int i = 1; i <= n; i++ ) modify( i, aa[i], +1 ); while( q-- ) { char ss[100]; scanf( "%s", ss ); if( ss[0] == 'q' ) { int l, r, k; scanf( "%d%d%d", &l, &r, &k ); printf( "%d\n", query(l,r,k) ); } else { int pos, val; scanf( "%d%d", &pos, &val ); modify( pos, val ); } } // fprintf( stderr, "mem used %d%%\n", int(tail - pool) * 100 / int(sizeof(pool)/sizeof(pool[0])) ); }
相关文章推荐
- POJ - 2155 Matrix (二维树状数组 + 区间修改 + 单点求值 或者 二维线段树 + 区间更新 + 单点求值)
- 动态区间第K大(树状数组+主席树)
- 【poj2104-求区间第k大数(不修改)】主席树/可持续化线段树
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
- [BZOJ 1901][ZOJ 2112]Dynamic Rankings(树状数组套主席树、动态区间第k大值查询)
- tyvj P1716 - 上帝造题的七分钟 二维树状数组区间查询及修改 二维线段树
- 动态区间第k小(主席树+线段树套树状数组)
- 主席树套树状数组 动态区间第k小
- 【bzoj1901】带修改的区间第k大 主席树+树状数组
- hdu1556 Color the ball【树状数组 || 线段树 || 技巧*区间修改】
- 【洛谷】线段树 树状数组区间修改区间查询
- 【算法系列学习】线段树vs树状数组 单点修改,区间查询 [kuangbin带你飞]专题七 线段树 A - 敌兵布阵
- 模板(线段树 + 树状数组 + 区间修改 + 区间查询)eg:POJ 3468 - A Simple Problem with Integers
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
- HDU 1166 敌兵布阵(树状数组 or 线段树 单点修改 区间求和)
- hdu4893 Wow! Such Sequence!,树状数组,线段树,单点修改,区间更新
- hdu1556 color the ball 树状数组区间更新单点查询(附线段树做法)与二维扩展
- HDU 4031 Attack(树状数组修改区间查询点)
- POJ 2892 Tunnel Warfare || HDU 1540(树状数组+二分 || 线段树的单点更新+区间查询)
- hdu 3727 Jewel 划分数+树状数组 求区间和当前段的第k大数