Description
给你很多线段的头S和尾E,问每一条线段中包含了多少个线段,(S和E相同不计在内)
Input
第一行为线段数量n,之后n行每行两个整数s和e表示该线段端点
Output
输出每一条线段包含的线段数量
Sample Input
3
1 2
0 3
3 4
0
Sample Output
1 0 0
Solution
将线段的s和e当做是(s,e)一个点,这样子把所有点画出来,题目要求就会变成:问每一个点的左上角有多少个点。排序的时候先y由大到小排,y相同时x由小到大排,然后类此stars那道题直接离散化处理即可
Code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 111111
int n,b[maxn];
struct node
{
int x,y,pos;
}s[maxn];
int cmp(node a,node b)//先按y降序排,再按x升序排
{
if(a.y!=b.y)
return a.y>b.y;
return a.x<b.x;
}
int getsum(int x)
{
int sum=0;
while(x>0)
{
sum+=b[x];
x-=x&-x;
}
return sum;
}
void update(int x,int v)
{
while(x<=maxn)
{
b[x]+=v;
x+=x&-x;
}
}
int main()
{
while(scanf("%d",&n),n)
{
int level[maxn]={0};
memset(b,0,sizeof(b));//初始化
for(int i=0;i<n;i++)
{
scanf("%d%d",&s[i].x,&s[i].y);
s[i].pos=i;
s[i].x++;//防止坐标等于0的情况出现
s[i].y++;
}
sort(s,s+n,cmp);
level[s[0].pos]=getsum(s[0].x);
update(s[0].x,1);
for(int i=1;i<n;i++)//判断区间重合的情况
{
if(s[i].x==s[i-1].x&&s[i].y==s[i-1].y)
level[s[i].pos]=level[s[i-1].pos];
else
level[s[i].pos]=getsum(s[i].x);
update(s[i].x,1);
}
for(int i=0;i<n;i++)
printf("%d%c",level[i],i==n-1?'\n':' ');
}
return 0;
}