hdu 2852 KiKi's K-Number (线段树,求大于x的第k小数)
2012-08-26 13:07
676 查看
http://acm.hdu.edu.cn/showproblem.php?pid=2852
(1)求比x大的第k个最小值。问题可以分解为两个子问题:
1)求不大于x 的数的个数t。(本质为求和)
2)求树里头的第t+y个数的值。(本质为定位)
(2)考虑过直接计算出结果:
即在区间(x, n)中寻找第y个数。
这种思想是可行的,但不适合已经构建的这棵树。因为已有的线段树只能从区间(1, 某数)开始查询,区间(x, n)与sum[]数组的描述方式对不上号。
(原有的sum[]数组中可能不含描述区间(x, n)的sum[i],并且一般情况下就是不包含对该区间的该描述)。
正确的分段式处理如下:
具体代码:
View Code
(1)求比x大的第k个最小值。问题可以分解为两个子问题:
1)求不大于x 的数的个数t。(本质为求和)
2)求树里头的第t+y个数的值。(本质为定位)
(2)考虑过直接计算出结果:
search(y, x, n, 1);
即在区间(x, n)中寻找第y个数。
这种思想是可行的,但不适合已经构建的这棵树。因为已有的线段树只能从区间(1, 某数)开始查询,区间(x, n)与sum[]数组的描述方式对不上号。
(原有的sum[]数组中可能不含描述区间(x, n)的sum[i],并且一般情况下就是不包含对该区间的该描述)。
正确的分段式处理如下:
x=add(1, x, 1, n, 1); y+=x; query(y, 1, n, 1);
具体代码:
View Code
#include<stdio.h> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 const int maxn=101000; int n=maxn, m; int sum[maxn<<2]; void pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l, int r, int rt) { sum[rt]=0; if(l==r) { return ; } int m=l+r>>1; build(lson); build(rson); } void inserts(int val, int l, int r, int rt) { if(l==r) { sum[rt]++; return ; } int m=l+r>>1; if(val<=m) inserts(val, lson); else inserts(val, rson); pushup(rt); } void deletes(int val, int l, int r, int rt) { if(l==r) { if(sum[rt]==0) printf("No Elment!\n"); else sum[rt]--; return ; } int m=l+r>>1; if(val<=m) deletes(val, lson); else deletes(val, rson); pushup(rt); } int add(int L, int R, int l, int r, int rt) { if(L<=l&&r<=R) { return sum[rt]; } int m=l+r>>1; int ret=0; if(L<=m) ret+=add(L, R, lson); if(R>m) ret+=add(L, R, rson); return ret; } void query(int p, int l, int r, int rt) { if(l==r) { printf("%d\n", l); return ; } int m=l+r>>1; if(p<=sum[rt<<1]) query(p, lson); else query(p-sum[rt<<1], rson); } int main() { while(scanf("%d", &m)!=EOF) { build(1, n, 1); for(int i=1;i<=m;i++) { int a, x, y; scanf("%d", &a); if(a==0) { scanf("%d", &x); inserts(x, 1, n, 1); } else if(a==1) { scanf("%d", &x); deletes(x, 1, n, 1); } else { scanf("%d%d", &x, &y); x=add(1, x, 1, n, 1); y+=x; if(y>sum[1]) printf("Not Find!\n"); else query(y, 1, n, 1); } } } return 0; }
相关文章推荐
- 线段树 树状数组 求大于某个值的第k小的数 hdu 2852 KiKi's K-Number
- HDOJ 题目2852 KiKi's K-Number(线段树求大于a的第k值)
- HDU 2852 KiKi's K-Number(动态过程求第K小数)
- 查询比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(线段树单点更新)
- HDU 2852 KiKi's K-Number 主席树
- HDU 2852——KiKi's K-Number(树状数组+二分查找, 第k大)
- hdu2852--KiKi's K-Number(线段树,求第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(BIT, 线段树,treap)
- HDU 2852 KiKi's K-Number(离线+树状数组)
- HDU 2852 KiKi's K-Number 树状数组
- hdu 2852 KiKi's K-Number
- HDU 2852 KiKi's K-Number