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;
}


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