zoukankan      html  css  js  c++  java
  • 牛客挑战赛43. C.最优公式 (二分,思维,切比雪夫距离与曼哈顿距离的转换)

    题目:传送门

    题意

     思路

    有两种做法:

    一.盲猜 a = b,那就直接二分 a,就完事儿了.

    二.按照题解那样的思路,这个会比较难想一点吧。

    #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;
     
    const LL mod = 1e9 + 7;
     
    int n, a[N];
     
    LL cal(int x) {
     
        int L = 1, R = 1, cnt = 1;
     
        while(L <= n && a[L] < x) L++;
     
        R = L; L--;
     
        LL ans = 0LL, now;
     
        while(cnt <= n) {
     
            if(!L) now = a[R] - x, R++;
     
            else if(R > n) now = x - a[L], L--;
     
            else if(x - a[L] < a[R] - x) now = x - a[L], L--;
     
            else now = a[R] - x, R++;
     
            ans += 1LL * (2LL * cnt - 1LL) * now;
     
            cnt++;
     
        }
     
        return ans;
     
    }
     
    void solve() {
     
        scanf("%d", &n);
     
        rep(i, 1, n) scanf("%d", &a[i]), a[i] *= 2;
     
        sort(a + 1, a + 1 + n);
     
        int l = 2, r = 1000000000;
     
        LL ans = inf;
     
        while(l <= r) {
     
            int mid = (l + r) >> 1;
     
            LL tmp1 = cal(mid), tmp2 = cal(mid + 1);
     
            if(tmp1 > tmp2) {
     
                ans = min(ans, tmp2);
     
                l = mid + 2;
     
            }
     
            else ans = min(ans, tmp1), r = mid - 1;
     
        }
     
        printf("%lld
    ", ans % mod);
     
    }
     
     
    int main() {
     
    //    int _; scanf("%d", &_);
    //    while(_--) solve();
     
        solve();
     
        return 0;
    }
    法1
    #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;
     
    const LL mod = 1e9 + 7;
     
    int n, a[N];
     
    LL pre[N];
     
    LL cal1(int x) {
     
        LL ans = 0LL;
     
        int now = n;
     
        rep(i, 1, n) {
     
            while(now > 1 && a[i] + a[now] > x) now--;
     
            if(a[i] + a[now] <= x) ans += now;
     
        }
     
        return ans >= n * 1LL * n / 2LL + 1LL;
     
    }
     
    LL cal2(int x) {
     
        LL ans = 0LL;
     
        int now = 1;
     
        rep(i, 1, n) {
     
            while(now < n && a[i] - a[now] > x) now++;
     
            if(a[i] - a[now] <= x) ans += (n - now + 1);
     
        }
     
        return ans >= n * 1LL * n / 2LL + 1LL;
     
    }
     
    void solve() {
     
        scanf("%d", &n);
     
        rep(i, 1, n) scanf("%d", &a[i]);
     
        sort(a + 1, a + 1 + n);
     
        rep(i, 1, n) pre[i] = pre[i - 1] + a[i];
     
        int l = 1, r = 1e9, ans;
     
        while(l <= r) {
     
            int mid = (l + r) >> 1;
     
            if(cal1(mid)) ans = mid, r = mid - 1;
     
            else l = mid + 1;
     
        }
     
        LL res = 0LL;  int pos = n;
     
        rep(i, 1, n) {
     
            while(pos > 1 && a[i] + a[pos] > ans) pos--;
     
            if(a[i] + a[pos] <= ans) {
     
                res += 1LL * pos * ans - pre[pos] - 1LL * pos * a[i];
     
                res += 1LL * (n - pos) * a[i] + (pre[n] - pre[pos]) - 1LL * (n - pos) * ans;
     
            }
     
            else res += 1LL * n * a[i] + pre[n]- 1LL * n * ans;
     
        }
     
        l = -1e9, r = 1e9;
     
        while(l <= r) {
     
            int mid = (l + r) >> 1;
     
            if(cal2(mid)) ans = mid, r = mid - 1;
     
            else l = mid + 1;
     
        }
     
        pos = 1;
     
        rep(i, 1, n) {
     
            while(pos < n && a[i] - a[pos] > ans) pos++;
     
            if(a[i] - a[pos] <= ans) {
     
                res += 1LL * ans * (n - pos + 1) - (a[i] * 1LL * (n - pos + 1) - pre[n] + pre[pos - 1]);
     
                res += 1LL * a[i] * 1LL * (pos - 1) - pre[pos - 1] - 1LL * ans * (pos - 1);
     
            }
     
            else res += 1LL * n * a[i] - pre[n] - 1LL * ans * n;
     
        }
     
        printf("%lld
    ",res % mod);
     
    }
     
     
    int main() {
     
    //    int _; scanf("%d", &_);
    //    while(_--) solve();
     
        solve();
     
        return 0;
    }
    法2
  • 相关阅读:
    块设备驱动框架分析(一)
    LIN总线协议
    LCD驱动分析(三)时序分析
    str_shuffle — 随机打乱一个字符串
    str_replace — 子字符串替换
    str_repeat — 重复一个字符串
    str_pad — 使用另一个字符串填充字符串为指定长度
    str_getcsv — 解析 CSV 字符串为一个数组
    ltrim — 删除字符串开头的空白字符(或其他字符)
    lcfirst — 使一个字符串的第一个字符小写
  • 原文地址:https://www.cnblogs.com/Willems/p/13715528.html
Copyright © 2011-2022 走看看