您的位置:首页 > 其它

hdu2852(线段树求第k大数)

2014-04-16 20:59 260 查看
题目链接:hdu2852

/*hdu2852 线段树求第k大数
题意:有三种操作,1、0 x 向容器中插入一个数x
2、1 x 在容器中删除一个数x
3、2 x k,求出容器中大于x的第k个元素。
思路:求出容器中大于x的第k个元素,可以先求出<=a的元素的数量cnt,
然后就等价于求区间[1..N]中第Kth = cnt+k的元素…
注意:相同的数可以插入多个
*/
#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <string>
#include <map>
using namespace std;
const int N = 100010;
#define lson rt<<1
#define rson rt<<1|1
struct node
{
int l,r,sum;
}s[N<<2];
int v
;//标记已经插入的数
void build(int l, int r, int rt)
{
s[rt].l = l; s[rt].r = r;
s[rt].sum = 0;
if(l == r) return;
int mid = (l+r) >> 1;
build(l, mid, lson);
build(mid+1, r, rson);
}
void update(int pos, int num, int rt)
{
if(s[rt].l == pos && pos == s[rt].r){
s[rt].sum += num;
return;
}
int mid = (s[rt].l + s[rt].r) >> 1;
if(pos <= mid)
update(pos, num, lson);
if(mid < pos)
update(pos, num, rson);
s[rt].sum = s[lson].sum + s[rson].sum;
}
int query(int num, int l, int r, int rt)
{
if(s[rt].l == s[rt].r) return s[rt].l;
int mid = (s[rt].l + s[rt].r) >> 1;
if(num <= s[lson].sum)
return query(num, l, r, lson);
else
return query(num-s[lson].sum, l, r, rson);
}
int getsum(int l, int r, int rt)
{
if(l <= s[rt].l && s[rt].r <= r)
return s[rt].sum;
int mid = (s[rt].l + s[rt].r) >> 1;
int ans = 0;
if(l <= mid)
ans += getsum(l, r, lson);
if(mid < r)
ans += getsum(l, r, rson);
return ans;
}
int main()
{
int n,i,x,k,op;
while(~scanf("%d",&n))
{
build(1, N, 1);
memset(v, false, sizeof(v));
while(n --){
scanf("%d",&op);
if(op == 0){
scanf("%d",&x);
update(x, 1, 1);
v[x] ++;
}
if(op == 1){
scanf("%d",&x);
if(!v[x])
puts("No Elment!");
else{
update(x, -1, 1);
v[x] --;
}
}
if(op == 2){
scanf("%d%d",&x,&k);
int cnt = getsum(1, x, 1);//查找<=x的数的个数
if(s[1].sum < cnt + k)
puts("Not Find!");
else{
int ans = query(cnt+k, 1, N, 1);
printf("%d\n",ans);
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树