HDU 2852 KiKi's K-Number (树状数组+二分)

题意:

给出一些操作:

0 x 在数组中加入一个数x

1 x 在数组中去掉一个数x

2 a k 在数组中查询比a大的第k小数


分析:

首先看到题目的数据范围 e<100000 ,发现数组完全可以存下,那么就好办了,一个萝卜一个坑~

对于0 1 操作,直接加入数组中计数

对于2操作,二分查询比a大的区间的第k小数,用树状数组或者线段树辅助区间查询

目测整体二分也可以做,但是代码量太大,容易出错,不推介


#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");

using namespace std;

#define INF 0x3f3f3f3f

int n;
int c[100005];

inline int lowbit(int x)
{
    return x&-x;
}

inline void update(int x,int val)
{
    for(; x<=100000; x+=lowbit(x)) c[x]+=val;
}

inline int query(int x)
{
    int  sum=0;
    for(; x>0; x-=lowbit(x)) sum+=c[x];
    return sum;
}

void Find(int k,int val)
{
    int l=val,r=100000;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(query(mid)-query(val)<k) l=mid+1;
        else r=mid-1;
    }
    if(query(l-1)-query(val)>=k) printf("%d\n",l-1);
    else printf("%d\n",l);
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        memset(c,0,sizeof c);
        for(int i=1; i<=n; i++)
        {
            int op;
            scanf("%d",&op);
            if(!op)
            {
                int x;
                scanf("%d",&x);
                update(x,1);
            }
            else if(op==1)
            {
                int x;
                scanf("%d",&x);
                if(query(x)-query(x-1)==0) printf("No Elment!\n");
                else update(x,-1);
            }
            else
            {
                int val,k;
                scanf("%d%d",&val,&k);
                if(query(100000)-query(val)<k) printf("Not Find!\n");
                else Find(k,val);
            }
        }
    }
    return 0;
}


你可能感兴趣的:(HDU 2852 KiKi's K-Number (树状数组+二分))