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

  • 相关阅读:
    魔控(电脑遥控器)
    百度网盘不限速下载网页版
    2019计算机科学与技术实训认识以及总结
    压缩文件破解
    废旧手机改造第二弹之电脑扩展屏幕和变成复制屏幕
    废旧手机改造之家居监控器
    关于志愿填报的一点点东西(大佬对计算机专业认识)
    html恶搞之无限弹窗
    java重点知识点整理
    推荐一个学java的网站
  • 原文地址:https://www.cnblogs.com/lwhinlearning/p/5661427.html
Copyright © 2011-2022 走看看