【题目链接】
【思路要点】
- 一个 1 0 13 10^{13} 1013 以内的数开根 6 6 6 次后一定会变成 1 1 1 ,因此有效的修改次数不会超过 6 N 6N 6N 。
- 设定一个阈值 α \alpha α ,若 k ≥ α k≥\alpha k≥α ,则暴力进行询问或修改,借助长链剖分求 k k k 级祖先,单次操作时间复杂度为 O ( N α ) O(\frac{N}{\alpha}) O(αN) 。
- 考虑 k < α k<\alpha k<α 的修改,用并查集维护每个点向上 k k k 的整数倍步第一个能够到达的非 1 1 1 的位置,再进行修改,就可以保证找到的位置上的修改有效。并查集大小为 O ( N α ) O(N\alpha) O(Nα) 。
- 考虑 k < α k<\alpha k<α 的询问,用 α \alpha α 棵树状数组维护子树和即可快速查询。
- 时间复杂度 O ( Q ∗ N α + 6 N L o g N ∗ α ) O(\frac{Q*N}{\alpha}+6NLogN*\alpha) O(αQ∗N+6NLogN∗α) 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 5; const int MAXLOG = 18; const int limit = 25; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) { x = max(x, y); } template <typename T> void chkmin(T &x, T y) { x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c =