• 火柴排队(归并)


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

  • 相关阅读:
    一分钟 解决Tomcat端口 占用问题
    Java 自定义注解
    Java 解析自定义XML文件
    Junit(手动/自动)加载
    Java思维题
    SSM框架中使用日志框架
    DAC
    SPI接口的FLASH
    晶振测试起振方法
    Jlink不报错的方法
  • 原文地址:https://www.cnblogs.com/lwhinlearning/p/5661427.html
Copyright © 2020-2023  润新知