The 3rd Universal Cup. Stage 15: Chengdu 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;
}