• CF957E Contact ATC


    二维偏序(逆序对)

    因为风速vf,-w<=vf<=w,因此我们可以算出每一艘船到达原点的时间的取值范围

    即取vf=w和vf=-w时,记ai为当vf=w时的用时,记bi为当vf=-w时的用时

    所以现在问题转化:为每一元素有两个值ai和bi,求有多少对下标i,j满足a[i]<=a[j]且b[i]>=b[j]

    这就是求二维偏序

    将每一个元素以a升序为第一关键字,b降序为第二关键字,然后求b的逆序对即可

    求逆序对用归并排序

    #include <bits/stdc++.h>
    using namespace std;
    int n,w;
    long long ans;
    double a[100010],b[100010];
    struct node
    {
        int f,x,v;
        double a,b;
    }sh[100010];
    double m_abs(double x)
    {
        if (x<0)
          return -x;
        else
          return x;
    }
    bool cmp(node x,node y)
    {
        return (x.a<y.a || (x.a==y.a && x.b>y.b));//先排序
    }
    void m_sort(int l,int r)//归并排序
    {
        if (l==r)
          return;
        int mid;
        mid=(l+r)/2;
        m_sort(l,mid);
        m_sort(mid+1,r);
        int ll,rr,now;
        now=0;
        ll=l;
        rr=mid+1;
        while (ll<=mid && rr<=r)
        {
            if (a[ll]<a[rr])
            {
                now++;
                b[now]=a[ll];
                ll++;
            }
            else
            {
                now++;
                b[now]=a[rr];
                rr++;
                ans+=(long long)mid-ll+1;//统计逆序对
            }
        }
        for (int i=ll;i<=mid;i++)
        {
            now++;
            b[now]=a[i];
        }
        for (int i=rr;i<=r;i++)
        {
            now++;
            b[now]=a[i];
        }
        for (int i=1;i<=now;i++)
        {
            a[l+i-1]=b[i];
        }
    }
    int main()
    {
        scanf("%d%d",&n,&w);
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d",&sh[i].x,&sh[i].v);
            if (sh[i].x>0)
              sh[i].f=1;
        }
        for (int i=1;i<=n;i++)//a表示当vf=w时的用时,b表示当vf=-w时的用时
        {
            if (sh[i].f==0)
            {
                sh[i].a=m_abs((sh[i].x*1.0)/((sh[i].v+w)*1.0));
                sh[i].b=m_abs((sh[i].x*1.0)/((sh[i].v-w)*1.0));
            }
            else
            {
                sh[i].b=m_abs((sh[i].x*1.0)/((sh[i].v-w)*1.0));
                sh[i].a=m_abs((sh[i].x*1.0)/((sh[i].v+w)*1.0));
            }
        }
        sort(sh+1,sh+1+n,cmp);
        for (int i=1;i<=n;i++)
          a[i]=sh[i].b;//求b的逆序对
        m_sort(1,n);
        printf("%lld
    ",ans);
    }
  • 相关阅读:
    大型项目使用Automake/Autoconf完成编译配置
    用C语言编写Windows服务程序的五个步骤
    RPC的发展历史(本质就是双方定义好协议,传递参数后远程调用)
    libuv和libev 异步I/O库的比较
    zlog 程序日志的库 交叉编译(Linux生成ARM库,观察执行步骤)
    应用服务
    EvnetBus
    this指向
    CPU使用率
    数据量小,创建索引有必要吗
  • 原文地址:https://www.cnblogs.com/huangchenyan/p/11179432.html
Copyright © 2020-2023  润新知