zoukankan      html  css  js  c++  java
  • [Luogu 1966] noip13 火柴排队

    [Luogu 1966] noip13 火柴排队

    Problem

    涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2

    其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。

    每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。

    输入输出格式

    输入格式:

    共三行,第一行包含一个整数 n,表示每盒中火柴的数目。

    第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。

    第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。

    输出格式:

    输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。

    输入输出样例

    输入样例#1: 
    4
    2 3 1 4
    3 2 1 4
    
    输出样例#1: 
    1
    输入样例#2: 
    4
    1 3 4 2
    1 7 2 4
    输出样例#2: 
    2

    说明

    【输入输出样例说明1】

    最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。

    【输入输出样例说明2】

    最小距离是 10,最少需要交换 2 次,比如:交换第 1 列的中间 2 根火柴的位置,再交换第 2 列中后 2 根火柴的位置。

    【数据范围】

    对于 10%的数据, 1 ≤ n ≤ 10;

    对于 30%的数据,1 ≤ n ≤ 100;

    对于 60%的数据,1 ≤ n ≤ 1,000;

    对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint

    Solution:

    因为题目要让a[i]-b[i]的平方和最小,就是要使a[i]和b[i]越接近越好

    那么我们可以先贪心的想一想,

    如果b[1]是b数组最小的,那么与之配对的a[1]是不是也应该最小才能保证对答案的影响最小

    所以说两列火柴对应的两根火柴在各列中高度的排名应该相同,

    证明就是将"若a1>a2且b1>b2,则有(a1-b1)^2+(a2-b2)^2<(a2-b1)^2+(a1-b2)^2"这个式子展开就可以得到

    那么这样我们就可以先把b进行排序,同时找到a数组所对应的顺序,

    最后在对a数组中找逆序对就是答案

    然后求逆序对可以用归并排序或者树状数组实现

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 const int N=100010,p=99999997;
     8 struct xint{int v,num;}a[N],b[N];
     9 int n,c[N],q[N],ans;
    10 int ask(int x,int res=0){
    11     while (x){res+=c[x]; x-=x&-x;} 
    12     return res;
    13 }
    14 void add(int x){
    15     while (x<=n){c[x]++; x+=x&-x;}
    16 }
    17 bool cmp(xint x,xint y){return x.v<y.v;}
    18 int main(){
    19     scanf("%d",&n);
    20     for (int i=1;i<=n;++i) scanf("%d",&a[i].v),a[i].num=i; 
    21     for (int i=1;i<=n;++i) scanf("%d",&b[i].v),b[i].num=i;
    22     sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cmp);
    23     for (int i=1;i<=n;++i) q[a[i].num]=b[i].num;
    24     for (int i=n;i>=1;--i){
    25         (ans+=ask(q[i]-1))%=p; add(q[i]);
    26     }
    27     printf("%d",ans);
    28 }
    View Code
  • 相关阅读:
    C#深入浅出 修饰符(二)
    HDU 5785 Interesting
    HDU 5783 Divide the Sequence
    HDU 5781 ATM Mechine
    UVA 714 Copying Books
    uva 1471 Defense Lines
    UVA 11134 Fabled Rooks
    UVA 11572 Unique Snowflakes
    UVA 11093 Just Finish it up
    UVA 10954 Add All
  • 原文地址:https://www.cnblogs.com/logic-yzf/p/7755668.html
Copyright © 2011-2022 走看看