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

来源:互联网 发布:腾讯云和阿里云 知乎 编辑:程序博客网 时间:2024/05/19 03:44

题意:给定一个容器,里面存放各种数值,规定三个操作,一个是在容器中增加一个数值,一个是在容器中删掉一个数值,一个是询问容器中比a大的数中第k大的数,将其输出。如果在删除过程中没有这个数,则输出"No Elment!",如果容器中没有比a大的第k个数,则输出"Not Find!".

 

此题因为是增加和删除元素的值,所以比较容易往树状数组的方向想,用树状数组当容器。采用一个标记数组来标记某个数值在容器中是否有。对于询问容器中比a大的第k个数,我们采用二分法,对a后面比它大的数进行二分,这里注意一下二分时必须是查看某点至a点有多少个比它大的,用Sum(mid) - Sum(a)就可以得到,我们这里就只要二分mid就可以了。

方法比较容易想到,代码的实现就必须要对树状数组理解清楚以及二分的思想及其步骤都要明确。

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!".
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;int a[111111],vis[111111];const int n=111111;void update(int x,int num){while(x<=n){a[x]+=num;x+=x&(-x);}}int getsum(int x){int s=0;while(x>0){s+=a[x];x-=x&(-x);}return s;}int main(){int m,i,j,mmax,com,x,y,l,r,mid;while(scanf("%d",&m)!=EOF){memset(a,0,sizeof(a));memset(vis,0,sizeof(vis));//mmax=0;while(m--){scanf("%d",&com);scanf("%d",&x);if(com==0) {update(x,1);//mmax=max(mmax,x);vis[x]++;}else if(com==1){if(getsum(x)-getsum(x-1)>0) {update(x,-1);vis[x]--;}else printf("No Elment!\n");}else{scanf("%d",&y);if(getsum(n)-getsum(x)<y) {printf("Not Find!\n");continue;}l=1;r=n;while(l<=r){mid=(l+r)/2;if(getsum(mid)-getsum(x)>y) r=mid-1;if(getsum(mid)-getsum(x)>y && getsum(mid-1)-getsum(x)<y) break;if(getsum(mid)-getsum(x)<y) l=mid+1;if(getsum(mid)-getsum(x)==y && vis[mid]==0) r=mid-1;if(getsum(mid)-getsum(x)==y && vis[mid]) break;}printf("%d\n",mid);}}}return 0;}


0 0