题意:给出m个操作,
0:是增加一个数,add(x,1)
1:是删除一个指定的数,这个是看sum(x) - sum(x-1)是否为0,为0的话则不存在,不为0的话,则add(x,-1)
0:是增加一个数,add(x,1)
1:是删除一个指定的数,这个是看sum(x) - sum(x-1)是否为0,为0的话则不存在,不为0的话,则add(x,-1)
2:是查询比x大的数中第k大的数
反思:做的时候没想到二分,长教训了,以后一定得注意查找的费时。不过这题也要注意二分的姿势。以后我做题得拿什么了。
上代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int ans[100010];
int n;
int maxn;
int getf(int x)
{
return x&(-x);
}
void add(int x,int d)
{
while(x<=100000)
{
ans[x] += d;
x += getf(x);
}
return ;
}
int getsum(int x)
{
int sum = 0;
while(x>0)
{
sum += ans[x];
x -= getf(x);
}
return sum;
}
int ex[100010]; // 不仅有标记的作用还可以顺便统计这个数的个数
int main()
{
while(scanf("%d", &n) != EOF)
{
memset(ans, 0, sizeof(ans));
memset(ex , 0, sizeof(ex));
int p;
int maxn = -1;
for(int i=1; i<=n; i++)
{
scanf("%d", &p);
if(p==0)
{
int a;
scanf("%d", &a);
add(a,1);
ex[a]++;
}
if(p==1)
{
int a;
scanf("%d", &a);
if(ex[a]==0){printf("No Elment!\n");continue;}
add(a,-1);
ex[a]--;
}
if(p==2)
{
int a,k;
scanf("%d %d",&a, &k);
// 已下为二分
int flag = -1;
int sum_a = getsum(a)+k;
int left = a+1; int right = 100001;
while(left<=right)
{
int mid = (left+right) / 2;
int qq = getsum(mid);
if(qq==sum_a)
{
if(ex[mid]!=0){flag=mid;break;}
right = mid - 1;
}
else if(qq<sum_a)
{
left = mid +1;
}else if(qq>sum_a)
{
if(qq-ex[mid]+1<=sum_a)
{
if(ex[mid]!=0){flag=mid;break;}
}
right = mid - 1;
}
}
if(flag!=-1)
{
printf("%d\n",flag);
}
else
{
printf("Not Find!\n");
}
}
}
}
return 0;
}
水波。