• AtCoder Beginner Contest 255


    C - ±1 Operation 1

    题目描述:

    给你一个等差数列,首项为A,公差为D,项数为N,问X和这N项中数字差的绝对值最小为多少

    思路:

    二分一下,找到离他最近的两项,求一个最小值就行

    注意公差可能为负数,所以可以分情况讨论,或者可以将这N个数倒着看就成了公差为正数的一个等差数列

    注意,如果二分的后找到大于等于x的位置是第一项或者第n+1项,那答案就只由一个数决定,否则是取左右两个的最小值,要特判一下

    #include <bits/stdc++.h>
    using namespace std;
    
    #define endl '\n'
    #define inf 0x3f3f3f3f
    #define mod7 1000000007
    #define mod9 998244353
    #define m_p(a,b) make_pair(a, b)
    #define mem(a,b) memset((a),(b),sizeof(a))
    #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
    #define debug(a) cout << "Debuging...|" << #a << ": " << a << "\n";
    typedef long long ll;
    typedef pair <int,int> pii;
    
    #define MAX 300000 + 50
    ll n, a, d, x;
    
    ll f(ll n){
        return a + (n - 1) * d;
    }
    
    void work(){
        cin >> x >> a >> d >> n;
        ll l = 1, r = n;
        while(l <= r){
            ll mid = (l + r) / 2;
            if(d >= 0){
                if(f(mid) > x)r = mid - 1;
                else if(f(mid) < x)l = mid + 1;
                else {
                    cout << 0 << endl;
                    return;
                }
            }
            else{
                if(f(mid) < x)r = mid - 1;
                else if(f(mid) > x)l = mid + 1;
                else {
                    cout << 0 << endl;
                    return;
                }
            }
        }
        if(d >= 0){
            ll id = l - 1;
            if(!id)cout << a - x << endl;
            else if(id == n)cout << x - f(n) << endl;
            else{
                cout << min(x - f(id), f(id + 1) - x) << endl;
            }
        }
        else{
            ll id = r + 1;
            if(id == 1)cout << x - a << endl;
            else if(id == n + 1)cout << f(n) - x << endl;
            else{
                cout << min(f(id - 1) - x, x - f(id)) << endl;
            }
        }
    }
    
    
    int main(){
        io;
        work();
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68

    D - ±1 Operation 2

    题目描述:

    给你数列A,若干次询问,每次询问都是问一个数字X,你可以对数列中任意一个数进行若干次加一或减一的操作,问将数组A的数字全部变成X需要多少次操作

    思路:

    排序后维护一个前缀和,对于每个X,我们将数组分成都小于X的数和都大于等于X的数,分别对这两部分求答案,这只需要知道数字个数和数字和即可,所以要维护一个前缀和

    #include <bits/stdc++.h>
    using namespace std;
    
    #define endl '\n'
    #define inf 0x3f3f3f3f
    #define mod7 1000000007
    #define mod9 998244353
    #define m_p(a,b) make_pair(a, b)
    #define mem(a,b) memset((a),(b),sizeof(a))
    #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
    #define debug(a) cout << "Debuging...|" << #a << ": " << a << "\n";
    typedef long long ll;
    typedef pair <int,int> pii;
    
    #define MAX 300000 + 50
    ll n, m, k, x;
    ll tr[MAX];
    ll sum[MAX];
    
    ll getsum(ll l, ll r){
        return sum[r] - sum[l - 1];
    }
    
    void work(){
        cin >> n >> m;
        for(int i = 1; i <= n; ++i)cin >> tr[i];
        sort(tr + 1, tr + 1 + n);
        for(int i = 1; i <= n; ++i)sum[i] = sum[i - 1] + tr[i];
        tr[n + 1] = 1e18;
        for(int i = 1; i <= m; ++i){
            cin >> x;
            ll id = upper_bound(tr + 1, tr + 2 + n, x) - tr;
            if(id == 1 || id == n + 1){
                cout << abs(n * x - getsum(1, n)) << endl;
            }
            else{
                cout << (id - 1) * x - getsum(1, id - 1) + getsum(id, n) - (n - id + 1) * x << endl;
            }
        }
    }
    
    
    int main(){
        io;
        work();
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    E - Lucky Numbers

    题目描述:

    给你N-1个数字S[i],以及M个数字X[i],现在定义数组A满足A[i] + A[i + 1] = S[i],i=1,2,...,N-1,问当M个数字在数组A中出现次数最多的时候是多少个

    思路:

    不难发现,当A[1]固定以后,数组A就固定了,所以我们要想办法把A[i]A[1]表示出来

    A[2] = S[1] - A[1]

    A[3] = S[2] - A[2] = S[2] - S[1] + A[1]

    A[4] = S[3] - A[3] = S[3] - S[2] + S[1] - A[1]

    我们设B[i] = S[i] - B[i], i >= 2, B[1] = 0

    所以 A [ i ] = B [ i ] + ( − 1 ) i + 1 ∗ A [ 1 ] A[i] = B[i] + (-1)^{i+1}*A[1] A[i]=B[i]+(1)i+1A[1]

    我们把A[1]分离出来,可以得到 A [ 1 ] = ( − 1 ) i + 1 ∗ ( A [ i ] − B [ i ] ) A[1] = (-1)^{i+1}* (A[i] - B[i]) A[1]=(1)i+1(A[i]B[i])

    因为我们想要的是A[i] = X[j],所以我们对于每个i,枚举每个X[j],计算出要想A[i] = X[j]A[1]的值,我们用map存一下数量,最后跑一遍map,找到第二键值最大的输出,记得开longlong

    #include <bits/stdc++.h>
    using namespace std;
    
    #define endl '\n'
    #define inf 0x3f3f3f3f
    #define mod7 1000000007
    #define mod9 998244353
    #define m_p(a,b) make_pair(a, b)
    #define mem(a,b) memset((a),(b),sizeof(a))
    #define io ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
    #define debug(a) cout << "Debuging...|" << #a << ": " << a << "\n";
    typedef long long ll;
    typedef pair <int,int> pii;
    
    #define MAX 300000 + 50
    ll n, m, k, x;
    ll s[MAX];
    ll br[MAX];
    
    void work(){
        cin >> n >> m;
        for(int i = 1; i < n; ++i){
            cin >> s[i];
        }
        for(int i = 2; i <= n; ++i){
            br[i] = s[i - 1] - br[i - 1];
        }
        map<ll, ll>mp;
        for(int j = 1; j <= m; ++j){
            cin >> x;
            for(int i = 1; i <= n; ++i){
                ++mp[(x - br[i]) * (i % 2 == 0 ? -1 : 1)];
            }
        }
        ll ans = 0;
        for(auto [x, y] : mp)ans = max(ans, y);
        cout << ans << endl;
    }
    
    
    int main(){
        io;
        work();
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
  • 相关阅读:
    第三方支付清算的信息流与资金流
    202109 CSP认证 | 脉冲神经网络
    算法分析与设计CH15:动态规划算法详解合集——装配线问题、矩阵链乘、LCS(最长公共子序列问题)、最大子数组和问题
    No150.精选前端面试题,享受每天的挑战和学习
    VRTK4⭐四.和 UI 元素交互
    NeurIPS 2022 | S-Prompts:摆脱新旧任务零和游戏,实现双赢的域增量学习方法
    Oracle统计信息问题排查常用SQL
    InnoDB - 锁(持续更新中...)
    PHP非对称与对称双向加密解密的方式
    【C++面向对象】1. 类、对象
  • 原文地址:https://blog.csdn.net/weixin_51216553/article/details/125547554