题意:在数轴[0,100000]内给定n个区间,区间端点为整数。问对于每个区间,有多少个区间能够包含这个区间。如果两个区间端点全部相同不算包含,只有一个端点相同的属于包含关系。
思路:树状数组。按照终止节点从大到小排序,相同的则按照起始节点从小到大,目的使得只有前面的区间可能包含后面的区间。遍历n处理两种情况:1、区间的两端点都和上一个完全相同,则输出值也和上一个区间相同;2、如果不是,那么计算该区间左端点之前有多少个左端点,也就是有多少个区间能够覆盖当前区间。最后将该区间的左端点树状数组进行更新。显然这种需要反复求和的问题用树状数组来做。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 100005
struct node{
int a,b,id;
}p[N];
int n,res[N],t[N];
int cmp(const struct node *a,const struct node *b){
if((*a).b == (*b).b)
return (*a).a - (*b).a;
return (*b).b - (*a).b;
}
int lowbit(int x){
return x&(-x);
}
int sum(int x){
int i,sum=0;
for(i = x;i>0;){
sum += t[i];
i -= lowbit(i);
}
return sum;
}
void add(int x){
int i;
for(i = x;i<N;){
t[i] += 1;
i += lowbit(i);
}
}
int main(){
freopen("a.txt","r",stdin);
while(scanf("%d",&n) && n){
int i;
memset(t,0,sizeof(t));
for(i = 0;i<n;i++){
scanf("%d %d",&p[i].a,&p[i].b);
p[i].id = i;
}
qsort(p,n,sizeof(struct node),cmp);
for(i = 0;i<n;i++){
if(i && p[i].a==p[i-1].a && p[i].b==p[i-1].b)
res[p[i].id] = res[p[i-1].id];
else
res[p[i].id] = sum(p[i].a+1);
add(p[i].a+1);
}
for(i = 0;i<n;i++)
printf("%d ",res[i]);
putchar('\n');
}
return 0;
}