题意
给你N个区间,问对于每一个区间i在这N个区间里存在多少个区间j使得i是j的真子集
思路
先对所有区间按第一关键字右端点降序第二关键字左端点升序的顺序排列,这样保证处理一个区间时符合条件的区间只会出现在它之前,用树状数组记录左端点的区间和,每一次只需要找左端点不超过现在这个左端点的数量,再把现在这个左节点加进去,需要注意的是还要减去有多少已经统计的跟当前区间范围一样的区间,因为是排好序的所以这个用一个变量记一下就好
代码
#include <cstdio>
#include <algorithm>
using namespace std;
int BIT[100002];
int ans[100001];
typedef struct block
{
int S;
int E;
int id;
}block;
bool cmp(block a,block b)
{
if(a.E!=b.E)
return a.E>b.E;
if(a.S!=b.S)
return a.S<b.S;
return a.id<b.id;
}
block cow[100001];
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int d)
{
while(x<=100001)
{
BIT[x]+=d;
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0;
while(x>0)
{
ans+=BIT[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
int N,cnt;
while(1)
{
scanf("%d",&N);
if(N==0)
break;
for(int i=0;i<N;i++)
scanf("%d%d",&cow[i].S,&cow[i].E);
for(int i=0;i<N;i++)
cow[i].id=i+1;
sort(cow,cow+N,cmp);
cnt=0;
for(int i=0;i<N;i++)
{
if(i!=0&&cow[i].S==cow[i-1].S&&cow[i].E==cow[i-1].E)
cnt++;
else cnt=0;
ans[cow[i].id]=sum(cow[i].S+1)-cnt;
add(cow[i].S+1,1);
}
for(int i=1;i<=N-1;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[N]);
for(int i=1;i<100001;i++)
BIT[i]=0;
}
return 0;
}