本文涉及知识点
[THUPC 2024 初赛] 转化
题目背景
小 E 在玩 Somzig 游戏的时候因为操作时间不够绷不住了,于是就有了这个题。
题目描述
小 E 有 n n n 种颜色的球,其中第 i i i 种有 a i a_i ai 个。有两类工具,第一类可以把一个指定颜色的球变成一个任意颜色的球;第二类可以把一个指定颜色的球变成两个这种颜色的球。一个变化之后的球也可以通过工具产生新的变化。关于第 i i i 种颜色的第一类工具有 b i b_i bi 个,第二类工具有 c i c_i ci 个。小 E 想知道,如果每一个工具最多只能使用一次,那么对于每种颜色 i i i,第 i i i 种颜色的球最后最多能有多少个。以及,小 E 最后最多能有多少个球。
输入格式
第一行一个正整数 n n n。
第二行 n n n 个整数,其中第 i i i 个表示 a i a_i ai。
第三行 n n n 个整数,其中第 i i i 个表示 b i b_i bi。
第四行 n n n 个整数,其中第 i i i 个表示 c i c_i ci。
输出格式
第一行 n n n 个整数,其中第 i i i 个表示如果每个工具最多使用一次,那么小 E 最后第 i i i 种颜色的球最多有多少个。
第二行一个整数,表示如果每个工具最多使用一次,那么小 E 最后最多能有多少个球。
样例 #1
样例输入 #1
2
1 2
1 2
1 0
样例输出 #1
4 3
4
提示
子任务
保证 1 ≤ n ≤ 351493 1\le n \le 351493 1≤n≤351493。
保证 0 ≤ a i , b i , c i ≤ 1 0 9 0\le a_i,b_i,c_i\le 10^9 0≤ai,bi,ci≤109。
题目使用协议
来自 THUPC2024(2024年清华大学学生程序设计竞赛暨高校邀请赛)初赛。
-
任何单位或个人都可以免费使用或转载本仓库的题目;
-
任何单位或个人在使用本仓库题目时,应做到无偿、公开,严禁使用这些题目盈利或给这些题目添加特殊权限;
-
如果条件允许,请在使用本仓库题目时同时提供数据、标程、题解等资源的获取方法;否则,请附上本仓库的 github 地址。
贪心
sab = ∑ \sum ∑min(a[i],b[i]) 。
计算第 i1种颜色最多多少个。
枚举各颜色j:
如果b[j]为0,d[j] = 0。
如果a[j]等于0,且sab>0 d[j] = min(1+c[j],b[j])-1。
如果sab=0,d[j] = 0。
如果a[j]不等于0 。d[j] = min(a[j]+c[j],b[j])
x1 =
∑
\sum
∑d -d[i1]
x1+= a[i1]
如果x1 > 0 x1 += c[i1]。
x1就是颜色i1的最多球数量。
性质一:如果sab>0,假定此球最初在i2,最终在i3,如果b[j]不为0。则i2
→
\rightarrow
→j
→
\rightarrow
→i3。
最多球
ans = 0 sab=0
按{a,b,c}降序排序。
先处理a>0
ans += (a+c)sab +=min(a+c,b)
再处理a为0,必须sab > 0
ans += c sab +=min(1+c,b)-1
逻辑
a>0,c全部生效,且sab增加或不变。
a=0,b>0,如果sab>0,c全部生效,且sab增加或不变。
a=0,b=0如果sab>0,c全部生效,且sab–。
代码
核心代码
#include <iostream>
#include <sstream>
#include <vector>
#include<map>
#include<unordered_map>
#include<set>
#include<unordered_set>
#include<string>
#include<algorithm>
#include<functional>
#include<queue>
#include <stack>
#include<iomanip>
#include<numeric>
#include <math.h>
#include <climits>
#include<assert.h>
#include<cstring>
#include <bitset>
using namespace std;
template<class T = int>
vector<T> Read(int n,const char* pFormat = "%d") {
vector<T> ret(n);
for(int i=0;i<n;i++) {
scanf(pFormat, &ret[i]);
}
return ret;
}
template<class T = int>
vector<T> Read( const char* pFormat = "%d") {
int n;
scanf("%d", &n);
vector<T> ret;
T d;
while (n--) {
scanf(pFormat, &d);
ret.emplace_back(d);
}
return ret;
}
string ReadChar(int n) {
string str;
char ch;
while (n--) {
do
{
scanf("%c", &ch);
} while (('\n' == ch));
str += ch;
}
return str;
}
template<class T1,class T2>
void ReadTo(pair<T1, T2>& pr) {
cin >> pr.first >> pr.second;
}
class Solution {
public:
vector<long long> Ans(const int N, vector<int>& a, vector<int>& b, vector<int>& c)
{
auto ans = Ans1(N, a, b, c);
ans.emplace_back(Ans2(N, a, b, c));
return ans;
}
vector<long long> Ans1(const int N, vector<int>& a, vector<int>& b, vector<int>& c)
{
long long sab = 0;
for (int i = 0; i < N; i++) {
sab += min(a[i], b[i]);
}
vector<int> d(N);
for (int i = 0; i < N; i++) {
if (0 == b[i]) { continue; }
if (0 != a[i]) { d[i] = min(b[i], a[i] + c[i]); continue; }
if (0 == sab) { continue; }
d[i] = min(1 + c[i], b[i]) - 1;
}
vector<long long> ans(N);
long long sum = accumulate(d.begin(), d.end(), 0LL);
for (int i = 0; i < N; i++) {
ans[i] = sum - d[i] + a[i];
if (ans[i] > 0) { ans[i] += c[i]; }
}
return ans;
}
long long Ans2(const int N, vector<int>& as, vector<int>& bs, vector<int>& cs)
{
vector<tuple<int, int, int>> abc;
for (int i = 0; i < N; i++) {
abc.emplace_back(as[i], bs[i], cs[i]);
}
sort(abc.begin(), abc.end());
long long sab = 0, ans = 0;
while (abc.size() && (get<0>(abc.back()) > 0)) {
auto [a, b, c] = abc.back();
ans += a + c;
sab += min(a + c, b);
abc.pop_back();
}
while (abc.size() && (sab > 0)) {
auto [a, b, c] = abc.back();
ans += c;
sab += min(1 + c, b) - 1;
abc.pop_back();
}
return ans;
}
};
int main() {
#ifdef _DEBUG
freopen("a.in", "r", stdin);
#endif // DEBUG
int n=0;
scanf("%d", &n);
auto a = Read<int>(n);
auto b = Read<int>(n);
auto c = Read<int>(n);
auto res = Solution().Ans(n,a,b,c);
#ifdef _DEBUG
/* printf("n=%d", n);
Out(a, "a=");
Out(b, ",b=");
Out(c, ",c="); */
#endif
for (int i = 0; i < n; i++) {
cout << res[i] << " ";
}
cout << std::endl << res.back() << std::endl;
return 0;
}
单元测试
int n;
vector<int> a, b, c;
TEST_METHOD(TestMethod11)
{
n = 2,a = { 1,2 }, b = { 1,2 }, c = { 1,0 };
auto res = Solution().Ans(n,a,b,c);
AssertEx({ 4,3,4 }, res);
}
扩展阅读
我想对大家说的话 |
---|
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。 |
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作 |
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注 |
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。 |
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。 |
如果程序是一条龙,那算法就是他的是睛 |
失败+反思=成功 成功+反思=成功 |
视频课程
先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。