比赛的时候没做出来,看了题解发现,没有正确理解一个条件,每次插入线段的长度是递增的!!!也就是不可能出现横跨要查询区间的情况。那么记录<=查询区间的右端点的线段数,减去<查询区间的左端点的线段数,就是答案了,初始化的时候做一次离散化。
#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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。