TLE了好久,终于过了
题意:
有一种容器,支持三种操作
给数e,在容器中插入一个元素e
给数e,在容器中删除一个元素e
给两个数a,k,查询比a大的第k小的数,输出
输入数据:
每个测试样例先给出一个数n,表示将要输入的指令条数
每一行的第一个数为这条指令的种类
0插入
1删除
2查询
解法:
显然树状数组满足题意,这里还用到二分查找,= =
二分一个没写好就死循环,哎
详细代码(有注释)
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
using namespace std;
#define MAX 101000
int c[MAX];
int b[MAX];
int lowbit(int x)
{
return x&(-1*x);
}
void update(int x,int val)
{
if(b[x]+val<0)
{
printf("No Elment!\n");
return;
}
b[x]+=val;
while(x<=100000)
{
c[x]+=val;
x+=lowbit(x);
}
}
int getsum(int x)
{
int ans=0;
while(x>=1)
{
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
void Find(int a,int k)
{
int l=a;
int r=100000;
int getsuma=getsum(a);
while(l<=r)
{
int mid=(l+r)>>1;
int temp=getsum(mid)-getsuma;
if(temp>=k)
{
if(temp-b[mid]<k)
{
printf("%d\n",mid);
return;
}
r=mid-1;
continue;
}
if(temp<k)
{
l=mid+1;
continue;
}
}
printf("Not Find!\n");
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int total;
while(scanf("%d",&total)!=EOF)
{
memset(c,0,sizeof(c));
memset(b,0,sizeof(b));
while(total--)
{
int type;
int e;
int a,k;
scanf("%d",&type);
switch(type)
{
case 0:
scanf("%d",&e);
update(e,1);
break;
case 1:
scanf("%d",&e);
update(e,-1);
break;
case 2:
scanf("%d %d",&a,&k);
if(getsum(100000)-getsum(a)<k)
{
printf("Not Find!\n");
break;
}
Find(a,k);
break;
}
}
}
return 0;
}