• 火柴排队(归并)


     NOIP2013提高组day1 第二题

    思路

    其中 Σ(ai-bi)^2=Σ(ai^1+bi^2-2aibi)差值最小的意思就是Σaibi最大,即顺序和最大

    可先把两盒火柴分别排序,然后用一个数组把一盒火柴的编号保存为相对应的另一盒火柴的下标,再对该数组归并求逆序对

    最小交换次数即求逆序对,也可用归并或树状数组来求

    以下是归并的代码O(3logn)

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define LL long long
    using namespace std;
    const int maxx=100001;
    int n,ys=99999997;
    LL ans;
    struct xx{
      int x,num;
    }a[maxx],b[maxx];
    int c[maxx],d[maxx];
    bool cmp(const xx a,const xx b)
    {
      return a.x<b.x;
    }
    void merge(int l,int r)
    {
      if(l==r)return;
      int mid=(l+r)>>1;
      merge(l,mid);
      merge(mid+1,r);
      int i=l,j=mid+1,k=l;
      while(i<=mid&&j<=r)
      {
        if(c[i]>c[j]){        //逆序对只算向左移的数字
           ans=(ans+mid-i+1)%ys;
          d[k++]=c[j++];
        }
        else   d[k++]=c[i++];
      }


      while(i<=mid)d[k++]=c[i++];
      while(j<=r) d[k++]=c[j++];


      for(int i=l;i<=r;i++)
      c[i]=d[i];
    }
    int main()
    {
      cin>>n;
      for(int i=1;i<=n;i++)
        scanf("%d",&a[i].x),a[i].num=i;
      for(int i=1;i<=n;i++)
        scanf("%d",&b[i].x),b[i].num=i;


      sort(a+1,a+n+1,cmp);
      sort(b+1,b+n+1,cmp);


      for(int i=1;i<=n;i++)  c[a[i].num]=b[i].num;


      merge(1,n);


      cout<<ans%ys;
      return 0;
    }

  • 相关阅读:
    「网络流 24 题」魔术球
    「网络流 24 题」圆桌聚餐
    「网络流 24 题」最小路径覆盖
    「网络流 24 题」太空飞行计划
    「网络流 24 题」搭配飞行员
    「网络流 24 题」负载平衡
    「网络流 24 题」数字梯形
    餐巾计划问题
    让Double类型完整显示,不用科学计数法显示E
    kotlin新工程
  • 原文地址:https://www.cnblogs.com/lwhinlearning/p/5661427.html
Copyright © 2020-2023  润新知