这个题比较难点,不过记得之前刚接触树状数组时候做过这题,当时搞明白了,可是今天看了后,又没点思路了。。。后来看了代码才明白
题目有两种操作,插入一个数,询问区间内有插入数的个数
由于数据比较大,所以也不能用简单的模版来套,依旧要离散化啊啊
先把所有的操作数给存储起来,包括询问的数,放一个数组里,然后排序之,另外按照操作的顺序再把数据放到队列里一份
之后从队列取数据,二分当前数据在数组里的下标,然后用下标来更新操作
另外需要注意的是,数组里不光存储了插入的数,询问操作的数也要放进去,这样才能给这俩数分配下标后进行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 } } } }