题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2852
题目大意:操作说明0:加入一个数字a;1:删除一个数字a,如果不纯在a输出no elment; 2:输出比a大并且第k小的数字;如果不存在,输出 not find!
算法:线段树
思路:建一颗[1, 100000]的线段树,例如,把5加入第5个根节点……;删数的时候,如果该根节点没有值,就输出no elment,否则update; 求第k小的数时,先判断一共比它大的有几个数字,然后求比a大的第m大的数
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define mid int m = (l+r) >> 1
int cnt[898989];
void update(int k, int c, int l, int r, int rt)
{
if(l == r)
{
if(cnt[rt] || c == 1)
cnt[rt] += c;
return ;
}
mid ;
if(k <= m)
update(k, c, lson);
else
update(k, c, rson);
cnt[rt] = cnt[rt << 1] + cnt[rt << 1 | 1];
}
int query(int k, int l, int r, int rt)
{
if(l == r)
return cnt[rt];
mid ;
if(k <= m)
return query(k, lson);
else
return query(k, rson);
}
int Query(int k, int l, int r, int rt)
{
if(l == r)
return 0;
mid ;
if(k <= m)
return Query(k, lson) + cnt[rt << 1 | 1];
else
return Query(k, rson);
}
int query1( int k, int l, int r, int rt)
{
if(l == r)
{
return l;
}
mid ;
if(cnt[rt << 1 | 1] < k)
return query1(k-cnt[rt << 1 | 1 ], lson);
else return query1(k, rson);
}
int main()
{
int a, b;
int n;
int op;
while(scanf("%d", &n) != EOF)
{
memset(cnt, 0, sizeof(cnt));
while(n --)
{
scanf("%d", &op);
if(op == 0)
{
scanf("%d", &a);
update(a, 1, 1, 100000, 1);
}
else if(op == 1)
{
scanf("%d", &a);
int k = query(a, 1, 100000, 1); //询问a点是否有数字
if(k == 0)
printf("No Elment!\n");
else
{
update(a, -1, 1, 100000, 1); //把a点的数字删除
}
}
else
{
scanf("%d%d", &a, &b);
int k = Query(a, 1, 100000, 1); //询问比a大的有几个数字
if(b <= k)
{
printf("%d\n", query1(k-b+1, 1, 100000, 1));//找到并且输出第b大的数字
}
else
{
printf("Not Find!\n");
}
}
}
}
return 0;
}