题解:CF2048F Kevin and Math Class
题意:很简单了,不再赘述。
做法:
首先我们注意到,因为 \(b_i\ge 2\),所以我们无脑全局操作 \(\log V\) 次之后一定可以满足条件。
同时注意到我们是对区间中最小的 \(b\) 以他为除数,所以说我们很自然可以去建出一个 \(b\) 的小根笛卡尔树。
发现对于一个笛卡尔树的子树,我们肯定是直接全部一起操作若干次,两个子树间再分别操作是最优的。
因为操作次数非常少,所以我们考虑直接 dp,\(dp_{u,j}\) 代表 \(u\) 的子树内,操作 \(j\) 次可以得到的答案。转移时,我们先枚举子树中的操作,显然是一个背包的转移方式,记得对 \(a_u\) 取 \(\max\)。合并完之后我们考虑对当前点 \(u\) 操作,那么就直接从前往后令 \(dp_{u,j}\) 对 \(\lceil\frac{dp_{u,j-1}}{b_u}\rceil\) 取 \(\min\) 即可。
复杂度 \(O(n\log^2n)\)。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e5 + 5, mx = 64;
int n, a[maxn], b[maxn], dp[maxn][70], st[maxn][21], lg[maxn];
int getmax(int x, int y) {
return (b[x] < b[y] ? x : y);
}
void prepare() {
lg[0] = -1;
for (int i = 1; i <= n; i++)
lg[i] = lg[i >> 1] + 1;
for (int j = 1; (1 << j) <= n; j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
st[i][j] = getmax(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);
}
int query(int l, int r) {
int k = lg[r - l + 1];
return getmax(st[l][k], st[r - (1 << k) + 1][k]);
}
int solve(int l, int r) {
if(l > r)
return 0;
if(l == r) {
dp[l][0] = a[l];
for (int i = 1; i <= mx; i++)
dp[l][i] = (dp[l][i - 1] + b[l] - 1) / b[l];
return l;
}
int mid = query(l, r);
int ls = solve(l, mid - 1), rs = solve(mid + 1, r);
// cout << dp[ls][0] << " " << dp[rs][0] << " " << l << " " << r << " " << mid << endl;
for (int i = 0; i <= mx; i++)
for (int j = 0; j <= mx; j++) {
if(i + j <= mx)
dp[mid][i + j] = min(dp[mid][i + j], max(dp[ls][i], max(dp[rs][j], a[mid])));
}
for (int i = 1; i <= mx; i++)
dp[mid][i] = min(dp[mid][i], dp[mid][i - 1]);
for (int i = 1; i <= mx; i++)
dp[mid][i] = min(dp[mid][i], (dp[mid][i - 1] + b[mid] - 1) / b[mid]);
return mid;
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
cin >> b[i], st[i][0] = i;
prepare();
for (int i = 1; i <= n; i++)
for (int j = 0; j <= mx; j++)
dp[i][j] = 9e18;
int rt = solve(1, n);
for (int i = 0; i <= mx; i++) {
if(dp[rt][i] <= 1) {
cout << i << endl;
return ;
}
}
}
signed main() {
int T;
cin >> T;
while(T--)
solve();
return 0;
}

浙公网安备 33010602011771号