zoukankan      html  css  js  c++  java
  • 火柴排队(归并)

     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;
    }

  • 相关阅读:
    机器学习-第四讲(模型升级)
    AI人脸匹对
    AI换脸
    人脸识别分析小Demo
    动态规划-线性DP&区间DP
    动态规划-背包问题
    数学知识-博弈论
    数学知识-组合数
    数学知识-扩展欧几里得
    数学知识-欧拉函数&快速幂
  • 原文地址:https://www.cnblogs.com/lwhinlearning/p/5661427.html
Copyright © 2011-2022 走看看