HDU2852 KiKi's K-Number (线段树求数列K大)

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

大致题意:

有三种操作:

第一种:向容器中加入数字A。 

第二种:从容器中删除数字A,若容器中不存在该数则输出"No Elment!"

第三种:输入A,K;求容器中比A大的数中的第K个数,若不存在则输出"Not Find!"


线段树每个节点存对应区域中共有多少个有效的数字,并实现单点更新。

对于操作一和操作二很另开数组容易实现。实现操作三时先求出比A大的数的个数B,接下来求有效元素中第B+K个数。

(同样大小的数可能有多个,都需要计数)

segTree[1]代表整个容器中有多少元素;显然,若segTree[1]<B+K则需要输出"Not Find!"。

查找区域中一共有多少有效元素实现简单也较容易理解,感觉上理解求容器中第K+B大的过程稍微难理解一些。

首先求出当前节点左儿子节点代表区域中有效元素个数,即segTree[lson]。

为求出当前区域中第K大的数,需要将K与segTree[lson]进行比较。若K<=segTree[lson]则说明第K大的数在当前节点左儿子代表区域中,

否则在右儿子节点代表区域中。若在右儿子代表的区域中需要把K修改为K-segTree[lson]。当查找到叶子节点时,该节点即为所求。


#include<iostream>
#include<cstring>
#include<cstdio>
#define lson node<<1,l,(l+r)/2
#define rson node<<1|1,(l+r)/2+1,r
using namespace std;
const int N = 1e5+10;


int segTree[N<<2];
int vis[N];

void update(int node,int l,int r,int pos,int n)
{
    if (l==r) segTree[node] += n;
    else
    {
        int mid = (l+r)>>1;
        if (pos<=mid) update(lson,pos,n);
        else update(rson,pos,n);
        segTree[node] = segTree[node<<1] + segTree[node<<1|1];
    }
}

int query(int node,int l,int r,int s,int e)
{
    if (l==r) return segTree[node];
    else if (l>=s && r<=e) return segTree[node];
    else
    {
        int ans = 0;
        int mid = (l+r)>>1;
        if (mid>=e)
            ans += query(lson,s,e);
        else if (mid<s)
            ans += query(rson,s,e);
        else
        {
            ans += query(lson,s,mid);
            ans += query(rson,mid+1,e);
        }
        return ans;
    }
}

int getans(int node,int l,int r,int cnt)
{
    if (l==r) return l;
    else
    {
        if (cnt<=segTree[node<<1])
            return getans(lson,cnt);
        else
            return getans(rson,cnt-segTree[node<<1]);
    }
}

int main()
{
    int cnt;
    int op,a,k;
    while (scanf("%d",&cnt)==1)
    {
        memset(segTree,0,sizeof (segTree));
        memset(vis,0,sizeof (vis));
        for (int i=0;i<cnt;i++)
        {
            scanf("%d%d",&op,&a);
            if (op==0)
            {
                vis[a]++;
                update(1,1,N,a,1);
            }
            else if (op==1)
            {
                if (!vis[a])
                {
                    printf("No Elment!\n");
                }
                else
                {
                    vis[a]--;
                    update(1,1,N,a,-1);
                }
            }
            else
            {
                scanf("%d",&k);
                int t = query(1,1,N,1,a);
                if (t+k>segTree[1])
                {
                    printf("Not Find!\n");
                }
                else
                {
                    printf("%d\n",getans(1,1,N,t+k));
                }
            }
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章