HDU 2852 KiKi's K-Number(线段树+树状数组)

KiKi‘s K-Number

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2603    Accepted Submission(s): 1202

Problem Description

For the k-th number, we all should be very familiar with it. Of course,to kiki it is also simple. Now Kiki meets a very similar problem, kiki wants to design a container, the container is to support the three operations.

Push: Push a given element e to container

Pop: Pop element of a given e from container

Query: Given two elements a and k, query the kth larger number which greater than a in container;

Although Kiki is very intelligent, she can not think of how to do it, can you help her to solve this problem?

Input

Input some groups of test data ,each test data the first number is an integer m (1 <= m <100000), means that the number of operation to do. The next m lines, each line will be an integer p at the beginning, p which has three values:

If p is 0, then there will be an integer e (0 <e <100000), means press element e into Container.

If p is 1, then there will be an integer e (0 <e <100000), indicated that delete the element e from the container

If p is 2, then there will be two integers a and k (0 <a <100000, 0 <k <10000),means the inquiries, the element is greater than a, and the k-th larger number.

Output

For each deletion, if you want to delete the element which does not exist, the output "No Elment!". For each query, output the suitable answers in line .if the number does not exist, the output "Not Find!".

Sample Input

5
0 5
1 2
0 6
2 3 2
2 8 1
7
0 2
0 2
0 4
2 1 1
2 1 2
2 1 3
2 1 4

Sample Output

No Elment!
6
Not Find!
2
2
4
Not Find!

线段树差点超时,感觉还是树状数组棒,但是毕竟刚学线段树,要练手

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 300010;
const int maxm = 100001;
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
#define MAX INT_MAX
#define MIN INT_MIN
struct node
{
    int left,right;
    int num;
}T[maxm<<2];
int ans = 0;
void Creat(int left,int right,int id)//建树
{
    T[id].left =left;
    T[id].right =right;
    T[id].num =0;
    if(T[id].left ==T[id].right )
        return ;
    Creat(left,(left+right)/2,2*id);
    Creat((left+right)/2+1,right,2*id+1);
}
void UPdata(int id,int i,int j)
{
    if(T[id].left<=i&&T[id].right >=i)
        T[id].num +=j;
    if(T[id].left ==T[id].right )
        return;
    if(i>T[id].right )
        return;
    if(i<T[id].left )
        return;
    int mid=(T[id].left +T[id].right )/2;
    if(i<=mid)
        UPdata(id*2,i,j);
    else
        UPdata(id*2+1,i,j);
}
void query(int id,int l,int r)
{
    int mid=(T[id].left +T[id].right)/2;
    if(T[id].left ==l&&T[id].right ==r)
    {
        ans+=T[id].num ;
        return;
    }
    if(r<=mid)
        query(2*id,l,r);
    else if(l>mid)
        query(2*id+1,l,r);
    else
    {
        query(2*id,l,mid);
        query(2*id+1,mid+1,r);
    }

}

int B_search(int x)
{
    int low = 1;
    int high = maxm;
    int mid,wz=-1;
    while(low<=high)
    {
        mid = (low + high) / 2;
       ans = 0;
        query(1,1,mid);
        if(ans>=x)
        {
            high = mid - 1;
            wz = mid;
        }
        else
        {
            low = mid+1;
        }
    }
    return wz;
}
int main()
{
    int n,a,b,k;
    while(~scanf("%d",&n))
    {
        Creat(1,100001,1);
        for(int i = 0;i<n;i++)
        {
            scanf("%d",&a);
        if(a==0)
        {
            scanf("%d",&b);
            UPdata(1,b,1);
        }
        else if(a==1)
        {
            scanf("%d",&b);
         ans = 0;
         query(1,b,b);
            if(!ans)
                puts("No Elment!");
            else
                UPdata(1,b,-1);
        }
        else if(a==2)
        {
            scanf("%d%d",&b,&k);

           ans = 0;
          query(1,1,b);
           int tem = B_search(ans+k);
           if(tem!=-1)
                printf("%d\n",tem);
            else
                puts("Not Find!");
        }
        }
    }
    return 0;
}

树状数组

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#define init(a) memset(a,0,sizeof(a))
using namespace std;
#define MAX INT_MAX
#define MIN INT_MIN
#define LL __int64
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 300010;
const int maxm = 100010;
using namespace std;
int c[maxn];
int hash[maxm];
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int w)
{
    while(x<=maxn)
    {
        c[x]+=w;
        x+=lowbit(x);
    }
}
int sum(int i)
{
    int s=0;
    while(i>0)
    {
        s += c[i];
        i =i - lowbit(i);
    }
    return s;
}
void B_search(int b,int k)
{
     int tem = sum(b);
    int low = b;
    int high = maxm;
    int mid;
    while(low <= high)
    {
        mid = (low + high) /2;
        int st = sum(mid);
        if(hash[mid]>0 && st-hash[mid]-tem<k&&st-tem>=k)
        {
            break;
        }
        if(st-tem<k)
        {
            low = mid + 1;
        }
        else
            high = mid - 1;
    }
    printf("%d\n",mid);
}
bool query(int b,int k)
{
    if(sum(maxn)-sum(b)<k)return 0;
    B_search(b,k);
    return 1;
}

int main()
{
    int n,a,b,k;
    while(scanf("%d",&n)!=EOF)
    {
        init(c);
        init(hash);

        for(int i=0;i<n;i++)
        {
            scanf("%d",&a);
            if(a==0)
            {
                scanf("%d",&b);
                add(b,1);
                hash[b]++;
            }
            else if(a==1)
            {
                scanf("%d",&b);
                if(hash[b]>0)
                {
                     add(b,-1);
                     hash[b]--;
                }
                else
                    puts("No Elment!");
            }
            else if(a==2)
            {
                scanf("%d%d",&b,&k);
               bool tep =  query(b,k);
               if(!tep)
                puts("Not Find!");
            }
        }
    }
    return 0;
}

HDU 2852 KiKi's K-Number(线段树+树状数组)

时间: 2024-08-28 17:42:16

HDU 2852 KiKi's K-Number(线段树+树状数组)的相关文章

hdu 2852 KiKi&#39;s K-Number (线段树)

hdu 2852 题意: 一个容器,三种操作: (1) 加入一个数 e (2) 删除一个数 e,如果不存在则输出 No Elment! (3) 查询比a大的数中的第k小数,不存在就输出 Not Find! 解法: 关于第三点,可以先查询小于等于a的数的个数cnt,然后直接查询第cnt+k小数就行了 . 二分+树状数组 或者 主席树(有点杀鸡用牛刀的感觉 ...) 也是可以做的  _(:з」∠)_ code:线段树 1 #include <iostream> 2 #include <cst

HDU 2852 KiKi&#39;s K-Number(动态过程求第K小数)

题意: 给出三种操作, 0 在容器中插入一个数. 1 在容器中删除一个数. 2 求出容器中大于a的第k大元素. 思路:可以用树状数组和线段树,显然a[1]+...+a[i]随i有明显的单调性,所以可以二分出答案 线段树时间复杂度比树状数组的常数大了几倍...所以线段树擦边过了 还有另外一种思路:二分只是二分出a[1]+...+a[i]的上界i,所以可以逆向考虑,从a[1]开始累加,直到到达k,这样的复杂度就由原来的 O(lgN*lgN) 变成O(lgN)了.难在累加的过程,线段树和树状数组是同样

HDU 2852 KiKi&#39;s K-Number(树状数组+二分)

KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2598    Accepted Submission(s): 1199 Problem Description For the k-th number, we all should be very familiar with it. Of course,t

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

HDU 2852 KiKi&#39;s K-Number【 树状数组 二分 】

题意:给出m个操作,0:是增加一个数,add(x,1)1:是删除一个指定的数,这个是看sum(x) - sum(x-1)是否为0,为0的话则不存在,不为0的话,则add(x,-1)2:是查询比x大的数中第k大的数,先求出比x小的个数s,假设比x大的数中第k大的数为y,那么比y小的个数有s+k个二分y的值来找 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath&g

hdu 2852 KiKi&#39;s K-Number

L - KiKi's K-Number Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description For the k-th number, we all should be very familiar with it. Of course,to kiki it is also simple. Now Kiki meets a very similar

线段树&amp;数状数组

线段树 单点修改,区间查询 #include<bits/stdc++.h> using namespace std; int n,q; long long num[1000010]; struct tree { int l,r; long long sum,max; }t[4000010]; void BuildTree(int,int,int); void Update(int,int,int,int,long long); long long Query(int,int,int,int,i

[HDU 2665&amp;POJ 2104]K-th Number(主席树)

Description Give you a sequence and ask you the kth big number of a inteval. Solution 主席树模板题 敲完辣,心情瞬间变好,我要下楼看运动会 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #define MAXN 100005

hdu 1394 Minimum Inversion Number 线段树 点更新

// hdu 1394 Minimum Inversion Number 线段树 点更新 // // 典型线段树的单点更新 // // 对于求逆序数,刚开始还真的是很年轻啊,裸的按照冒泡排序 // 求出最初始的逆序数,然后按照公式递推,结果就呵呵了 // // 发现大牛都是用线段树和树状数组之类的做的,而自己又在学 // 线段树,所以就敲了线段树. // // 线段树的节点保存一段区间( L,R )内0,1...n一共出现了多少个. // 因为每个数是0,1,2...n-1且没有重复的数字. /