The 3rd Universal Cup. Stage 15: Chengdu I. Good Partitions

I. Good Partitions

非预期解,思考方式和官解完全不同,所以写一个题解供参考。

题面就不复述了,上面链接里有,直接看题解。


不妨考虑映射到 \([a_0, a_1, a_2, \ldots, a_{n - 1}]\),我们划分为长为 \(k\) 的段时,每个段可以被描述为 \([a_{ik}, a_{ik+1}, \ldots, a_{(i+1)k - 1}]\),容易发现,如果存在一组 \(a_j > a_{j + 1}\),当且仅当 \(j \bmod k \neq 0\)

我们可以记录 \(num[i]\) 数组表示模 \(k\) 时,\(a_j > a_{j + 1}\) 的位置满足 \(j \bmod k \neq 0\) 的个数,可以得出,一个划分 \(k\) 合法的条件是 \(num[k] = 0\)

\(0, 1, 2, 3, 4 \,\, \mid \, position\)
\(4, 3, 2, 6, 1 \,\, \mid \,num[1, 2, 3, 4, 5] = [0, 1, 3, 2, 3]\)
\(4, 5, 2, 6, 1 \,\, \mid \,num[1, 2, 3, 4, 5] = [0, 0, 2, 1, 2]\)
\(4, 5, 5, 6, 1 \,\, \mid \,num[1, 2, 3, 4, 5] = [0, 0, 1, 0, 1]\)

不等关系是不优秀的,如果我们转化为恰好等于 \(0\),那么本题就迎刃而解了。

考虑 \(j \bmod k = 0\) 的时候我们加 \(1\) 会发生什么。

\(0, 1, 2, 3, 4 \,\, \mid \, position\)
\(4, 3, 2, 6, 1 \,\, \mid \,num[1, 2, 3, 4, 5] = [3, 2, 0, 1, 0]\)
\(4, 5, 2, 6, 1 \,\, \mid \,num[1, 2, 3, 4, 5] = [3, 3, 1, 2, 1]\)
\(4, 5, 5, 6, 1 \,\, \mid \,num[1, 2, 3, 4, 5] = [3, 3, 2, 3, 2]\)

我们原先统计 \(0\) 的个数变成了我们统计最大的数的个数,也就是说,每次操作后,我只需要知道最大的数有多少个就可以了,这是好办的,因为任何数模 \(1\) 都为 \(0\),因此 \(num[1]\) 最大,它的个数就是我们所求的答案。

预处理因数,暴力修改,时间复杂度 \(O(n\ln{n} + q\operatorname{d}(n))\)

参考代码

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, q, a[N];
int num[N];
int cnt[N];
vector<int> factors[N];

void init()
{
    for (int i = 1; i < N; i ++ )
        for (int j = i; j < N; j += i)
            factors[j].push_back(i);
}

void modify(int x, int op)
{
    for (auto d : factors[x])
    {
        cnt[num[d]] -- ;
        num[d] += op;
        cnt[num[d]] ++ ;
    }
}

void solve()
{
    cin >> n >> q;
    for (int i = 0; i <= n; i ++ ) num[i] = cnt[i] = 0;
    cnt[0] = n;
    for (int i = 0; i < n; i ++ ) cin >> a[i];
    for (int i = 1; i < n; i ++ )
        if (a[i - 1] > a[i])
            modify(i, 1);
    if (n == 1) cout << "1\n";
    else cout << cnt[num[1]] << "\n";
    while (q -- )
    {
        int x, d;
        cin >> x >> d;
        x -- ;
        if (x && a[x - 1] > a[x] && a[x - 1] <= d) modify(x, -1);
        else if (x && a[x - 1] <= a[x] && a[x - 1] > d) modify(x, 1);
        if (x < n - 1 && a[x] > a[x + 1] && d <= a[x + 1]) modify(x + 1, -1);
        else if (x < n - 1 && a[x] <= a[x + 1] && d > a[x + 1]) modify(x + 1, 1);
        a[x] = d;
        if (n == 1) cout << "1\n";
        else cout << cnt[num[1]] << "\n";
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    init();
    int T = 1;
    cin >> T;
    while (T -- ) solve();
    return 0;
}
posted @ 2024-12-11 21:32  YipChip  阅读(11)  评论(0编辑  收藏  举报