当前位置: 首页 > 工具软件 > kiki-re > 使用案例 >

hdu 2852 KiKi's K-Number(线段树单点更新)

姚煜
2023-12-01

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

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!
使用线段树更新,查询操作,难点在于操作3(p is 2)。这题过的确实不易,开始的方案是这样的:
WA:
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=1e5;
struct node{
    int l,r,count;
    int mid(){  return (l+r)/2;   }
}tree[maxn<<2];
void build(int root,int a,int b){
    tree[root].l=a;
    tree[root].r=b;
    tree[root].count=0;
    if(a==b)  return ;
    int m=tree[root].mid();
    build(2*root,a,m);
    build(2*root+1,m+1,b);
}
void insert(int root,int a,int b,int number){
    if(a==b){
         tree[root].count++;
         return ;
    }
    int m=(a+b)/2;
    if(number<=m)insert(2*root,a,m,number);
    else if(number>m)insert(2*root+1,m+1,b,number);
    tree[root].count=tree[2*root].count+tree[2*root+1].count;
}
bool work;
void delet(int root,int a,int b,int number){
    if(tree[root].count<1){
        work=0;
        return ;
    }
    if(a==b){
         tree[root].count--;
         return ;
    }
    int m=(a+b)/2;
    if(number<=m)delet(2*root,a,m,number);
    else if(number>m)delet(2*root+1,m+1,b,number);
    tree[root].count=tree[2*root].count+tree[2*root+1].count;
}
int findres;
void inquiry(int root,int a,int b,int q1,int q2){
    if(tree[root].count<1){
         printf("Not Find!\n");
         return ;
    }
    if(a==b){
         printf("%d\n",a);
         return ;
    }
    int m=(a+b)/2;
    if(q1<=m&&q2<=tree[2*root].count)
         inquiry(2*root,a,m,q1,q2);
    else {
        if(q1>=tree[2*root].r)q2=q2-tree[2*root].count;
        inquiry(2*root+1,m+1,b,q1,q2);
    }
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int m,p,a,b;
    while(cin>>m){
        build(1,1,maxn);
        while(m--){
            scanf("%d",&p);
            if(p==0){
                scanf("%d",&a);
                insert(1,1,maxn,a);
            }
            else if(p==1){
                scanf("%d",&a);
                work=1;
                delet(1,1,maxn,a);
                if(work==0){
                   printf("No Elment!\n");
                }
            }
            else {
                scanf("%d%d",&a,&b);
                inquiry(1,1,maxn,a,b);
            }
        }
    }
    return 0;
}
我怀疑是操作3的函数写的不严谨把。学习一种新的写法:把统计占用结点sum单独写一个函数,删除和加入全写成update,最后的查找函数在sum正常工作的情况下找到第K大的数。
AC:
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=1e5;
struct node{
    int l,r,count;
    int mid(){  return (l+r)/2;   }
}tree[maxn<<4];
void build(int root,int a,int b){
    tree[root].l=a;
    tree[root].r=b;
    tree[root].count=0;
    if(a==b)  return ;
    int m=tree[root].mid();
    build(2*root,a,m);
    build(2*root+1,m+1,b);
}
void update(int root,int l,int r,int number,int val){
    if(l==r){
         tree[root].count+=val;
         return ;
    }
    int m=tree[root].mid();
    if(number<=m)update(2*root,l,m,number,val);
    else update(2*root+1,m+1,r,number,val);
    tree[root].count=tree[2*root].count+tree[2*root+1].count;
}
int sum(int root,int l,int r,int ql,int qr){  // l and r is necessary
    if(qr<l||ql>r){
        return 0;
    }
    if(ql<=l&&qr>=r){ //care >= == <=
        return tree[root].count;
    }
    int m=(l+r)/2;
    return sum(2*root,l,m,ql,qr)+sum(2*root+1,m+1,r,ql,qr);
}
int findgoal(int root,int l,int r,int number){
    if(l==r){
        return tree[root].l;
    }
    int m=(l+r)/2;
    if(number>tree[2*root].count){
        //if(l==r){
          //  return tree[root].l;
        //}
        return findgoal(2*root+1,m+1,r,number-tree[2*root].count);
    }
    return  findgoal(2*root,l,m,number);
}
int main()
{
    //freopen("cin.txt","r",stdin);
    int m,p,a,b;
    while(cin>>m){
        build(1,1,maxn);
        while(m--){
            scanf("%d",&p);
            if(p==0){
                scanf("%d",&a);
                update(1,1,maxn,a,1);
                //for(int i=20;i>0;i--)cout<<tree[i].count<<" "; cout<<endl;
            }
            else if(p==1){
                scanf("%d",&a);
                if(sum(1,1,maxn,1,a)==sum(1,1,maxn,1,a-1)){
                    printf("No Elment!\n");
                }
                else update(1,1,maxn,a,-1);
            }
            else {
                scanf("%d%d",&a,&b);
                int goal=sum(1,1,maxn,1,a)+b;
                //cout<<"goal: "<<goal<<endl;
                int ans=findgoal(1,1,maxn,goal);
                //cout<<"ans: "<<ans<<endl;
                if(ans==maxn)printf("Not Find!\n");
                else printf("%d\n",ans);
            }
        }
    }
    return 0;
}

还有一份长得很像的 Runtime Error,最开始我真没看出来哪里不同,后来我发现tree[maxn<<4]; 如果写成tree[maxn<<2];  或者:tree[maxn*5] 居然会RE,我又惊呆了。。。



 类似资料: