D. Prefix Purchase
D. Prefix Purchase
You have an array of size , initially filled with zeros (). You also have an array of integers of size .
Initially, you have coins. By paying coins, you can add to all elements of the array from the first to the -th element ( for all ). You can buy any any number of times. A purchase is only possible if , meaning that at any moment must hold true.
Find the lexicographically largest array that can be obtained.
An array is lexicographically smaller than an array of the same length if and only if in the first position where and differ, the element in array is smaller than the corresponding element in .
Input
The first line contains a single integer () — the number of test cases. This is followed by a description of the test cases.
The first line of each test case contains a single integer () — the size of arrays and .
The second line of each test case contains integers () — the array .
The third line of each test case contains a single integer () — the number of coins you have.
It is guaranteed that the sum of all values across all test cases does not exceed .
Output
For each test case, output integers — the lexicographically largest array that can be obtained.
Example
input
4
3
1 2 3
5
2
3 4
7
3
3 2 1
2
6
10 6 4 6 3 4
7
output
5 0 0
2 1
2 2 2
2 2 2 2 2 1
Note
In the first test case, cannot be greater than , and if we buy five times, we will run out of money, so .
In the second test case, cannot be greater than , but we can buy and once each (buying twice is not possible), so .
解题思路
如果有下标 ,并且 ,那么很明显买入 要比 更优,因为不仅前缀的长度 比 大,而且价格也不超过 。因此要把所有这样的 删掉,有点类似于单调栈,最后栈内的元素(存的是下标)是严格递增的,满足 ,则 。
然后就是贪心地选择栈内的哪些元素购买,使得序列 的字典序最大,这步卡了我很久。设栈的大小为 ,栈底元素是 ,由于栈底元素对应的 最小,因此要使得 的前 个元素字典序最大,那么在下标 处最多能买入 次。对于前 个元素而言这是上界,否则如果在其他位置 买入,那么字典序肯定不如这个上界大,因为 。
买入后会有剩余,记作 ,在保持 的前 个元素字典序最大的前提下,看看能不能买入其他的 来替换 ,使得字典序更大。对于 的话,如果想要用 替换,那么需要 的花费,而最多可以替换 次。另外还要考虑到在 买入的次数 ,即替换的次数不能超过这个值,因此实际上最多能替换 次。
记剩余的 ,同理对于 ,我们应该用 来替换 次。而不用再考虑用 来替换,这是因为将 替换成 ,等价于先将 替换成 ,再将 替换成 ,两种替换方式的花费是一样的。而上一步已经通过最大次数来将 替换成 ,以使得 的字典序尽可能大,因此 是无法再将 替换成 ,因此不足以将 替换成 。
以此类推,可以发现每一次只需将前一个元素替换即可。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int a[N];
int stk[N], tp;
int ans[N];
void solve() {
int n, m;
scanf("%d", &n);
tp = 0;
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
while (tp && a[i] <= a[stk[tp]]) { // 删掉下标小于i且花费大于等于a[i]的元素
tp--;
}
stk[++tp] = i; // 栈里存的是下标
}
scanf("%d", &m);
memset(ans, 0, n + 10 << 2);
ans[0] = 2e9;
for (int i = 1; i <= tp; i++) {
int t = min(ans[stk[i - 1]], m / (a[stk[i]] - a[stk[i - 1]])); // 最多替换的次数
ans[stk[i]] = t;
ans[stk[i - 1]] -= t;
m -= t * (a[stk[i]] - a[stk[i - 1]]);
}
for (int i = n; i; i--) {
ans[i] += ans[i + 1];
}
for (int i = 1; i <= n; i++) {
printf("%d ", ans[i]);
}
printf("\n");
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
CodeTON Round 6 (Div. 1 + Div. 2, Rated, Prizes!) Editorial:https://codeforces.com/blog/entry/120524
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17746337.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效