这个题比较难点,不过记得之前刚接触树状数组时候做过这题,当时搞明白了,可是今天看了后,又没点思路了。。。后来看了代码才明白
题目有两种操作,插入一个数,询问区间内有插入数的个数
由于数据比较大,所以也不能用简单的模版来套,依旧要离散化啊啊
先把所有的操作数给存储起来,包括询问的数,放一个数组里,然后排序之,另外按照操作的顺序再把数据放到队列里一份
之后从队列取数据,二分当前数据在数组里的下标,然后用下标来更新操作
另外需要注意的是,数组里不光存储了插入的数,询问操作的数也要放进去,这样才能给这俩数分配下标后进行get操作
ps:这里用了下系统函数bsearch,感觉不错,不过也手写了一个二分,时间当然还是没系统的好
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
#define MAX 200010
using namespace std;
int c[MAX],a[MAX],k;
bool flag[MAX];
queue<int> Q;
int bs(int key,int l,int r)
{
int mid=(l+r)>>1;
if(l==r)return l;
if(key>a[mid])return bs(key,mid+1,r);
else return bs(key,l,mid);
}
int cmp(const void *a,const void *b)
{
return *(int*)a-*(int*)b;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int x)
{
while(x<MAX)
{
c[x]++;
x+=lowbit(x);
}
}
int get(int x)
{
int sum=0;
while(x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
void init()
{
memset(flag,false,sizeof(flag));
memset(c,0,sizeof(c));
while(!Q.empty())
Q.pop();
k=0;
}
int main()
{
int n,q,l,r,t,ca=1;
char s[10];
while(scanf("%d",&t)!=EOF)
{
init();
for(int i=0;i<t;i++)
{
scanf("%s%d",s,&l);
Q.push(l);
a[k++]=l;
if(s[0]=='Q')
{
scanf("%d",&r);
Q.push(r);
a[k++]=r;
flag[i]=true;
}
}
qsort(a,k,sizeof(int),cmp);
for(int i=0;i<t;i++)
{
n=Q.front();Q.pop();
n=bs(n,0,k);//n=(int*)bsearch(&n,a,k,sizeof(int),cmp)-a;
if(!flag[i])
{
update(n+1);//更新时候把所有下标都+1;
continue;
}
else
{
q=Q.front();Q.pop();
q=bs(q,0,k);//q=(int*)bsearch(&q,a,k,sizeof(int),cmp)-a;还是stl的稍微快点
if(n>q)swap(n,q);
printf("%d\n",get(q+1)-get(n));//由于所有下标+1,get(q)-get(n-1)都+1
}
}
}
}

浙公网安备 33010602011771号