zoukankan      html  css  js  c++  java
  • 火柴排队

    传送门 https://www.luogu.org/problemnew/show/P1966

    欲求min∑(ai-bi)^2,我们可以先将它展开,得到min∑(ai^2-2*ai*bi+bi^2),ai^2与bi^2的值是一定的,因此只需考虑min∑ai*bi(系数2也忽略)。

    不难发现这样一条性质:当序列a中的数与序列b中的数处在相同位置,且它们在各自序列中相对大小相同时,得到的ai*bi最优。

    证明:详见洛谷题解(逃。

    那么具体如何操作呢,众所周知,这是来自gg给的PPT里在归并排序下的题,所以这道题一定离不开归并排序(其实还可以用树状数组。

    为了得到满足上述性质的两个序列,可以利用下标的单调性。

    2 3 1 4   3 2 1 4    ------>  1 2 3 4  1 2 3 4 ------>   c[3] = 3,c[1] = 2,c[2] = 1,c[4]=4.

    1 2 3 4   1 2 3 4               3 1 2 4  3 2 1 4

    c[b[i].num] = a[i].num,c下标与它的值所“差”的地方,就是我们需要在a或b序列中调整的地方,对c进行归并排序求逆序对即可。

    附上只有80pts的代码

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int mod = 99999997;
    const int N = 1e5+1;
    inline int read()
    {
        static char ch;
        while((ch = getchar()) < '0' || ch > '9');
        int ret = ch - 48;
        while((ch = getchar()) >= '0' && ch <= '9')
            ret = ret * 10 + ch - 48;
        return ret;
    }
    struct node
    {
        int x,num;
    }a[N],b[N];
    int n,t[N],c[N];
    long long int ans;
    void Merge(int l,int m,int r)
    {
        int i = l,k = l,j = m+1;
        while(i <= m && j <= r)
        {
            if(c[i] > c[j])
            {
                t[k++] = c[j++];
                ans += (m-i+1)%mod; 
            }
            else t[k++] = c[i++];     
        }
        while(i <= m) t[k++] = c[i++];
        while(j <= r) t[k++] = c[j++];
        for(int i = l;i <= r;i++) c[i] = t[i];
    }
    void Merge_sort(int l,int r)
    {
        if(l < r)
        {
            int mid = (l+r)>>1;
            Merge_sort(l,mid);
            Merge_sort(mid+1,r);
            Merge(l,mid,r);
        }
    }
    bool cmp(node p,node q){return p.x < q.x;}
    int main()
    {
        n = read();
        for(int i = 1;i <= n;i++)
        {
            a[i].x = read();
            a[i].num = i;
        }
        for(int i = 1;i <= n;i++)
        {
            b[i].x = read();
            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[b[i].num] = a[i].num;
        Merge_sort(1,n);
        printf("%lld",ans);
        return 0;
    } 
  • 相关阅读:
    算法演示工具
    1198:逆波兰表达式
    1315:【例4.5】集合的划分
    1192:放苹果
    1191:流感传染
    1354括弧匹配检验
    1331【例1-2】后缀表达式的值
    1307高精度乘法
    1162字符串逆序
    1161转进制
  • 原文地址:https://www.cnblogs.com/peppa/p/9831352.html
Copyright © 2011-2022 走看看