zoukankan      html  css  js  c++  java
  • 第五届华中区程序设计邀请赛暨武汉大学第十四届校赛 网络预选赛 A Minimum Sum 树状数组

    Problem 1603 - Minimum Sum
     
    Description

    There are n numbers A[1] , A[2] .... A[n], you can select m numbers of it A[B[1]] , A[B[2]] ... A[B[m]]  ( 1 <= B[1] < B[2] .... B[m] <= n ) such that Sum as small as possible.

    Sum is sum of abs( A[B[i]]-A[B[j]] ) when 1 <= i < j <= m.

    Input
    There are multiple test cases.
    First line of each case contains two integers n and m.( 1 <= m <= n <= 100000 )
    Next line contains n integers A[1] , A[2] .... A[n].( 0 <= A[i] <= 100000 )
    It's guaranteed that the sum of n is not larger than 1000000.
    Output
    For each test case, output minimum Sum in a line.
    Sample Input
    4 2
    5 1 7 10
    5 3
    1 8 6 3 10
    Sample Output
    2
    8
     
    题意:
     
      给你n个数,让你选M个数来,使得 sigma abs( A[B[i]]-A[B[j]] ) when 1 <= i < j <= m.最小
     
    题解:
        
        排序过后,就是选择连续的m个数了
      由于数的范围小,我们在统计连续和的时候 利用BIT优化
     
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <vector>
    using namespace std;
    const int N = 1e5+10, M = 50, mod = 1e9+9, inf = 1e9+9;
    typedef long long ll;
    
    ll sum;
    
    int n,m,a[N];
      int C[N],A[N];
        int lowbit(int x) {
            return x&(-x);
        }
        void add(int x, int add) {
            for (; x < N; x += lowbit(x)) {
                C[x] += add;
            }
        }
        int sums(int x) {
            int s = 0;
            for (; x > 0; x -= lowbit(x)) {
              s+=C[x];
            }
            return s;
        }
    int main() {
        while(scanf("%d%d",&n,&m)!=EOF) {
                memset(C,0,sizeof(C));
            for(int i=1;i<=n;i++) scanf("%d",&a[i]);
            sort(a+1,a+n+1);
            sum = 0;
            for(int i=1;i<=m;i++) {
                sum+=(a[i]*(i-1)-sums(i));
                add(i,a[i]);
            }
      // cout<<sum<<endl;
            ll ans = sum;
            for(int i=m+1;i<=n;i++) {
                sum -= (sums(i)-sums(i-m)-a[i-m]*(m-1));
              // cout<<(sums(i)-sums(i-m+1)-a[i-m]*(m-1))<<endl;
              //  cout<<sum<<endl;
                sum += (a[i]*(m-1)-sums(i)+sums(i-m));
                add(i,a[i]);
                ans = min(ans,sum);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
      
  • 相关阅读:
    LeetCode "Super Ugly Number" !
    LeetCode "Count of Smaller Number After Self"
    LeetCode "Binary Tree Vertical Order"
    LeetCode "Sparse Matrix Multiplication"
    LeetCode "Minimum Height Tree" !!
    HackerRank "The Indian Job"
    HackerRank "Poisonous Plants"
    HackerRank "Kundu and Tree" !!
    LeetCode "Best Time to Buy and Sell Stock with Cooldown" !
    HackerRank "AND xor OR"
  • 原文地址:https://www.cnblogs.com/zxhl/p/5372325.html
Copyright © 2011-2022 走看看