zoukankan      html  css  js  c++  java
  • CodeForces

    Increasing by Modulo

    题目大意:

    选一个下标的长度为(k)的子序列(b_1,b_2,...,b_k),使得(a_{b_i} = (a_{b_i} + 1) \% m),求使得序列满足单调非降的最小操作次数。

    思路:

    (f(x))为能否经过(x)次操作数使得序列满足条件,不难看出这是一个单调函数,考虑利用二分求出最小操作次数,假设当前的二分的操作次数为(x)

    对于check的编写,我们首先考虑到,题目中的操作对于序列第(i)位数字(a[i])的变换是相对独立的,也就是说,我们只需check序列经过(x)次变换后的结果序列,即判断每个数字的变换次数是否符合当前二分的(x),并且判断能否让结果序列满足单调非降。

    对于确定二分操作次数的上界,我们考虑到,经过(m)次变换之后,我们一定可以将所有数字都变为(0),由此确定出二分上界。

    接下来,我们贪心的进行变换。

    假设当前check到第(i)位数字(a[i])

    1. 如果(a[i] = a[i - 1]),不需要进行变换。
    2. 如果(a[i] < a[i - 1]),要想满足单调不降就需要对(a[i])进行操作,如果(a[i])(a[i - 1])的距离大于了二分的次数(x),直接return,否则,使(a[i] := a[i - 1]),让序列升的不那么多(这里是不让他上升)以贪心的期望后面会更加容易的满足单调非降。
    3. 如果(a[i] > a[i - 1]),那么如果能变为(a[i - 1])就变为(a[i - 1]),否则不改变。

    举个例子

    a[i - 1]   a[i]
        5        3
        4        7
    

    主要是a[i] > a[i - 1]时:

      a[i - 1]
    |----------|
             a[i]                    m
    |-----------****************|--------------|
    

    因为操作是加操作,所以除非满足(m - (a[i] - a[i - 1]) leq x),使得(a[i])变换为(a[i - 1]),否则,(a[i])只能落在上图‘*’号的左边或者右边,落在左边则不满足单调不降的条件,落在右边则还不如不变换。

    Code:
    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    using pii = pair<int, int>;
    const double eps = 1e-6;
    const int N = 300010;
    //const int N = 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1000000007; //998244353
    const int dir[8][2] = {0, 1, 0, -1, 1, 0, -1, 0,/* dir4 */ -1, -1, -1, 1, 1, -1, 1, 1};
    ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
    ll powmod(ll a, ll b) { ll res = 1; a %= mod; assert(b >= 0); for (; b; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res; }
    template<class T> bool ckmin(T& a, const T& b) { return b < a ? a = b, 1 : 0; }
    template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
    
    ll n, m, a[N], oa[N];
    
    bool ck(ll x) {
        for (int i = 1; i <= n; i++)
            a[i] = oa[i];
        for (ll i = 1; i <= n; i++) {
            if (a[i] == a[i - 1]) {
                continue;
            } else if (a[i] < a[i - 1]) {
                if (a[i - 1] - a[i] > x) {
                    return false;
                } else {
                    a[i] = a[i - 1];
                }
            } else {
                if (m - (a[i] - a[i - 1]) <= x) {
                    a[i] = a[i - 1];
                }
            }
        }
        return true;
    }
    
    int main() {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin >> n >> m;
        for (int i = 1; i <= n; i++) {
            cin >> oa[i];
        }
        ll lf = 0, rt = m/* m次操作可以让所有数都变为0 */, mid;
        while (lf < rt) {
            mid = (lf + rt) >> 1;
            if (ck(mid)) {
                rt = mid;
            } else {
                lf = mid + 1;
            }
        }
        cout << lf << "
    ";
        return 0;
    }
    
  • 相关阅读:
    UVA
    UVA
    模板——扩展欧几里得算法(求ax+by=gcd的解)
    UVA
    模板——2.2 素数筛选和合数分解
    模板——素数筛选
    Educational Codeforces Round 46 (Rated for Div. 2)
    Educational Codeforces Round 46 (Rated for Div. 2) E. We Need More Bosses
    Educational Codeforces Round 46 (Rated for Div. 2) D. Yet Another Problem On a Subsequence
    Educational Codeforces Round 46 (Rated for Div. 2) C. Covered Points Count
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/14808983.html
Copyright © 2011-2022 走看看