652D:Nested Segments
题意简述
给出若干条线段,问每条线段包含多少条线段。
保证所有线段端点不重合。
数据范围
1≤n≤2∗105
−109≤li<ri≤109
思路
按照左端点降序,右端点升序排列。
树状数组支持区间修改单点查询。
每次修改将当期线段右端点向后区间+1。
代码
#include<cstdio>
#include<algorithm>
using namespace std;
struct BIT{
static const int size=400000;
int d[400010];
int lowbit(int x)
{
return x&(-x);
}
void modify(int pos,int val)
{
while (pos<=size)
d[pos]+=val,pos+=lowbit(pos);
}
int query(int pos)
{
int ret=0;
while (pos)
ret+=d[pos],pos-=lowbit(pos);
return ret;
}
}T;
struct data{
int val,id;
bool operator < (const data &n1) const
{
return val<n1.val;
}
}d[400010];
struct Line{
int l,r,id;
bool operator < (const Line &n1) const
{
return l==n1.l ? r<n1.r : l>n1.l;
}
}L[200010];
int n,maxnum;
int ans[2000010];
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&d[i].val);
d[i].id=i;
scanf("%d",&d[i+n].val);
d[i+n].id=i+n;
}
sort(d+1,d+2*n+1);
maxnum=0;
for (int i=1;i<=n*2;i++)
{
if (d[i].val!=d[i-1].val)
maxnum++;
if (d[i].id>n)
L[d[i].id-n].r=maxnum;
else
L[d[i].id].l=maxnum;
}
for (int i=1;i<=n;i++)
L[i].id=i;
sort(L+1,L+n+1);
for (int i=1;i<=n;i++)
{
ans[L[i].id]=T.query(L[i].r);
T.modify(L[i].r+1,1);
}
for (int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}