题意:
给了N个线段(N<=10000)..现在请输出每个线段被多少个线段包围了..[L,R]要包围线段[l,r]..则L<=l && R>=l && R-L > r-l...
题解:
这题就是上半年南京邀请赛的热身题...
将所有线段按起点从小到大排序..当起点相同时终点从大到小排序..然后按排好的顺序..按拍好的顺序访问每个线段...先统计包围它的有多少个..然后将其的终点插入到树状数组里..
值得注意的是相同线段的处理...要存起来..记下个数..然后一起做..而答案又要存到每个一线段上去...
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<set>
#include<map>
#include<time.h>
#define ll long long
#define oo 1000000009
#define MAXN 100000
#define pi acos(-1.0)
#define esp 1e-30
#define MAXD 4
using namespace std;
struct node
{
int l,r,id;
}L[MAXN];
int N,sum[MAXN+2],ans[MAXN+2];
bool cmp(node a,node b)
{
if (a.l!=b.l) return a.l<b.l;
return a.r>b.r;
}
void update(int x,int k)
{
while (k<=MAXN)
{
sum[k]+=x;
k+=k&(-k);
}
}
int query(int k)
{
int ans=0;
while (k)
{
ans+=sum[k];
k-=k&(-k);
}
return ans;
}
int main()
{
int i,t,m;
while (~scanf("%d",&N) && N)
{
for (i=1;i<=N;i++) scanf("%d%d",&L[i].l,&L[i].r),L[i].id=i;
sort(L+1,L+1+N,cmp);
memset(sum,0,sizeof(sum)),L[0].l=-1;
for (i=1;i<=N;i++)
{
m=1,t=i;
while (t!=N && L[t+1].l==L[t].l && L[t+1].r==L[t].r) t++,m++;
ans[L[t].id]=query(MAXN)-query(L[i].r-1),update(m,L[i].r);
for (;i<t;i++) ans[L[i].id]=ans[L[t].id];
}
for (i=1;i<N;i++) printf("%d ",ans[i]);
printf("%d\n",ans[N]);
}
return 0;
}