zoukankan      html  css  js  c++  java
  • 糖果传递(思维,推式子)

    题目:传送门

    题意

    有n个小朋友坐成一圈,每人有a[i]个糖果。

    每人只能给左右两人传递糖果。

    每人每次传递一个糖果代价为1。

    求使所有人获得均等糖果的最小代价。

    1n1000000
    数据保证一定有解。

    思路

    设第一个人给了第 n 个人 x1 个糖果,第二个人给了第一个人 x2 个糖果,.....第 n 个人给了第 n - 1 个人 xn 个糖果。

    答案就是 abs(x1) + abs(x2) + abs(x3) + ..... + abs(xn)

    最终每个人的糖果数 result 是总的糖果数 s 除以人数 n,即 result = s / n;

    对于第一个人来说有:

    a[1] - x1 + x2 = result;

    依次列出有:

    a[2] - x2 + x3 = result;

    a[3] - x3 + x4 = result;

    ....

    化简一下有

    x2 = x1 + result - a[1] = x1 - (a[1] - result); 

    x3 = x2 + result - a[2] = x1 - (a[1] - result) - (a[2] - result);

    ......

    我们让

    c[1] = a[1] - result; 

    c[2] = (a[1] - result) + (a[2] - result);

    ......

    那么就有 xi =  x1 - c[i - 1];  则最终的答案就是 abs(x1) + abs(x1 - c[1]) + abs(x1 - c[2]) ..... + abs(x1 - c[n - 1]) ;

    观察发现,abs(x1) + abs(x1 - c[1]) + abs(x1 - c[2]) ..... + abs(x1 - c[n - 1]) 类似于一维坐标上,所有点到某个定点的总距离和。

    那么,我们可以对 c[i] 排序,定点为所有点中点时,距离和最小。

    #include <bits/stdc++.h>
    #define LL long long
    #define ULL unsigned long long
    #define UI unsigned int
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF 0x3f3f3f3f
    #define inf LLONG_MAX
    #define PI acos(-1)
    #define fir first
    #define sec second
    #define lb(x) ((x) & (-(x)))
    #define dbg(x) cout<<#x<<" = "<<x<<endl;
    using namespace std;
    
    const int N = 1e6 + 5;
    
    int n, a[N];
    
    LL c[N];
    
    void solve() {
    
        scanf("%d", &n);
    
        LL result = 0;
    
        rep(i, 1, n) scanf("%d", &a[i]), result += a[i];
    
        result /= n;
    
        rep(i, 1, n - 1) c[i] = c[i - 1] + a[i] - result;
    
        sort(c + 1, c + 1 + n);
    
        LL ans = 0LL;
    
        int pos = (n + 1) / 2;
    
        rep(i, 1, n) {
    
            ans += abs(c[i] - c[pos]);
    
        }
    
        printf("%lld
    ", ans);
    
    }
    
    
    int main() {
    
    //    int _; scanf("%d", &_);
    //    while(_--) solve();
    
        solve();
    
        return 0;
    }
  • 相关阅读:
    并不对劲的bzoj3932: [CQOI2015]任务查询系统
    并不对劲的bzoj4868: [Shoi2017]期末考试
    并不对劲的bzoj1853:[SCOI2010]幸运数字
    并不对劲的bzoj4199: [Noi2015]品酒大会
    并不对劲的bzoj1500: [NOI2005]维修数列
    并不对劲的hdu4777
    并不对劲的线段树套平衡树
    44.Linked List Cycle II(环的入口节点)
    43.Word Break(看字符串是否由词典中的单词组成)
    42.Flatten Binary Tree to Linked List
  • 原文地址:https://www.cnblogs.com/Willems/p/13818003.html
Copyright © 2011-2022 走看看