开始看这题时以为是线段树区间更新,误以为和poj2528差不多,然后上手打了。。。到末尾时发现有个点不一样,那就是删除,还要恢复到之前的状态,这个不会了。又从树状数组入手,发现用树状数组很简单。这题的主要思想,求得左端点大于等于左端点的线段的个数,然后再求得右端点大于该线段右端点的个数,然后两数相减得出答案,用两个树状数组维护即得到答案
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<cstring>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int M=2*1e5+20;
typedef struct
{
int op,id;
}PP;
PP p[M];
typedef struct
{
int st,End,id;
}OP;
OP ad[M];
typedef struct
{
int num,id;
}Trans;
Trans tr[2*M];
bool cmp(const Trans&a,const Trans&b)
{
return a.num<b.num;
}
int del[M];
int start[M*2],eend[2*M];
void add(int n,int x,int *s)
{
while(n<2*M)
{
s[n]+=x;
n+=n&(-n);
}
}
int getsum(int n,int *s)
{
int sum=0;
while(n>=1)
{
sum+=s[n];
n-=n&(-n);
}
return sum;
}
int main()
{
int n,T=1;
while(~scanf("%d",&n))
{
memset(start,0,sizeof(start));
memset(eend,0,sizeof(eend));
int i, t=0,s=1,ff,b;
for(i=1;i<=n;i++)
{
scanf("%d%d",&ff,&b);
if(ff==0)
{
++t;
p[i].id=t;
p[i].op=0;
tr[2*t-1].num=b;
tr[2*t-1].id=t;
tr[2*t].num=b+t;
tr[2*t].id=-1*t;
}
else
{
p[i].id=s;
p[i].op=1;
del[s++]=b;
}
}
sort(tr+1,tr+1+2*t,cmp);
int tt=1,temp=tr[1].num;
for(i=1;i<=t*2;i++)
{
if(temp<tr[i].num)
{
tt++;
temp=tr[i].num;
}
if(tr[i].id>0)
{
ad[tr[i].id].st=tt;
ad[tr[i].id].id=tr[i].id;
}
else
{
ad[tr[i].id*(-1)].End=tt;
ad[tr[i].id*(-1)].id=tr[i].id*(-1);
}
}
printf("Case #%d:\n",T++);
for(int i=1;i<=n;i++)
{
int d=p[i].id;
if(p[i].op==0)
{
int st=ad[d].st,ed=ad[d].End,sum1=0,sum2=0;
add(st,1,start);
add(ed,1,eend);
sum1=getsum(2*M-1,start)-getsum(st-1,start);
sum2=getsum(2*M-1,eend)-getsum(ed,eend);
printf("%d\n",sum1-1-sum2);
}
else
{
int s=del[d];
int st=ad[s].st,ed=ad[s].End;
add(st,-1,start);
add(ed,-1,eend);
}
}
}
return 0;
}