比赛的时候没做出来,看了题解发现,没有正确理解一个条件,每次插入线段的长度是递增的!!!也就是不可能出现横跨要查询区间的情况。那么记录<=查询区间的右端点的线段数,减去<查询区间的左端点的线段数,就是答案了,初始化的时候做一次离散化。
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
#define ll long long
#define FOR(i,x,y) for(int i = x;i < y;i ++)
#define IFOR(i,x,y) for(int i = x;i > y;i --)
#define N 220000
using namespace std;
struct Commends{
int l,r;
int type;
}cmd[N];
int n,cnt,num[N<<1],l[N],r[N],m;
map <int,int> mat;
int lowbit(int x) {return (x&(-x));}
int C1[N<<1],C2[N<<1];
void Modify_1(int x,int val){
while(x <= n){
C1[x] += val;
x += lowbit(x);
}
}
void Modify_2(int x,int val){
while(x <= n){
C2[x] += val;
x += lowbit(x);
}
}
int GetSum_1(int x){
int sum = 0;
while(x > 0){
sum += C1[x];
x -= lowbit(x);
}
return sum;
}
int GetSum_2(int x){
int sum = 0;
while(x > 0){
sum += C2[x];
x -= lowbit(x);
}
return sum;
}
int Query(int u,int v){
int t2 = GetSum_2(v);
int t1 = GetSum_1(u-1);
return t2-t1;
}
int main(){
//freopen("test.in","r",stdin);
int tCase = 0;
while(~scanf("%d",&m)){
printf("Case #%d:
",++tCase);
int v,b;
n = cnt = 0;
FOR(i,0,m){
scanf("%d%d",&v,&b);
cmd[i].type = v;
if(!v){
n ++;
num[cnt++] = b;
num[cnt++] = b+n;
cmd[i].l = b;
cmd[i].r = b+n;
l[n] = b;
r[n] = b+n;
}
else{
cmd[i].l = l[b];
cmd[i].r = r[b];
}
}
n = 0;
sort(num,num+cnt);
mat[num[0]] = ++n;
FOR(i,1,cnt){
if(num[i] != num[i-1])
mat[num[i]] = ++n;
}
memset(C1,0,sizeof(C1));
memset(C2,0,sizeof(C2));
FOR(i,0,m){
if(!cmd[i].type){
printf("%d
",Query(mat[cmd[i].l],mat[cmd[i].r]));
Modify_1(mat[cmd[i].l],1);
Modify_2(mat[cmd[i].r],1);
}
else{
Modify_1(mat[cmd[i].l],-1);
Modify_2(mat[cmd[i].r],-1);
}
}
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。