线段树HDU 2852

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2852

代码风格:www.notonlysuccess.com


题目大意:操作说明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;
}


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值