CodeForces 652D Nested Segments

离散化+树状数组

先对坐标离散化,把每条线段结尾所在点标1,

询问某条线段内有几条线段的时候,只需询问这段区间的和是多少,询问结束之后再把这条线段尾部所在点标为0

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;

const int maxn=2*1e5+10;
struct X
{
    int x,y,ans,id;
}p[2*maxn];
int n;
int lsh[2*maxn],tot;
int c[2*maxn];

bool cmp(const X&a,const X&b)
{
    return a.x<b.x;
}

bool cmp2(const X&a,const X&b)
{
    return a.id<b.id;
}

int lowbit(int x)
{
    return x&(-x);
}

void update(int pos,int val)
{
    while(pos<=2*n)
    {
        c[pos]=c[pos]+val;
        pos=pos+lowbit(pos);
    }
}

int getsum(int pos)
{
    int res=0;
    while(pos>0)
    {
        res=res+c[pos];
        pos=pos-lowbit(pos);
    }
    return res;
}

int get(int num)
{
    int l=0,r=tot-1;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(lsh[mid]<=num)
        {
            if(lsh[mid]==num) return mid+1;
            else l=mid+1;
        }
        else r=mid-1;
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int li,ri; scanf("%d%d",&li,&ri);
        lsh[tot++]=li; lsh[tot++]=ri;
        p[i].x=li; p[i].y=ri; p[i].id=i;
    }
    sort(lsh,lsh+tot);
    for(int i=1;i<=n;i++)
    {
        p[i].x=get(p[i].x);
        p[i].y=get(p[i].y);
    }
    sort(p+1,p+1+n,cmp);
    memset(c,0,sizeof c);
    for(int i=1;i<=n;i++) update(p[i].y,1);

    for(int i=1;i<=n;i++)
    {
        if(p[i].x+1>p[i].y-1) p[i].ans=0;
        else p[i].ans=getsum(p[i].y-1)-getsum(p[i].x+1);
        update(p[i].y,-1);
    }
    sort(p+1,p+1+n,cmp2);
    for(int i=1;i<=n;i++) printf("%d
",p[i].ans);
    
    return 0;
}
原文地址:https://www.cnblogs.com/zufezzt/p/5322288.html