Codeforces Round #617(div3) A-E2题解
Posted honey-cat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #617(div3) A-E2题解相关的知识,希望对你有一定的参考价值。
A. Array with Odd Sum
? 有n个数的数组a,询问它是否有一个奇数和。
- 满足:索引 i != j 且 ai != aj,可进行操作: ai = aj
- 思路:
- 数组中必须有奇数,才可以产生奇数和 -> 全为偶数 -> 不可以
- n为偶数,数组中至少存在一个偶数 - 全为奇数,但n是偶数 -> 不可以
- 首先判断不存在奇数和的两种情况即可
B. Food Buying
? 有s块钱,每次买东西花费x元,会获得x / 10的回报(向下取整)。询问当前s,可以消费的最大值。
- 思路
- 首先,当s < 10,不会获得回报,只能消费s元
- 贪心:消费x,获得x / 10的回报 --> 每次消费的x均为不大于当前s的最大的10的倍数,同样,在s < 10时为最后一次消费
C. Yet Another Walking Robot
? 机器人开始位与(0,0),机器人的移动方式: L: x - 1; R x + 1; U: y + 1 D: y - 1;输入一串长为n,包含机器人移动命令的字符串,需要删除不必要的路径(最短),保证最后到达位置不变。若不能删除,输出-1;否则,输出删除的最短路径的左右端点索引
-
思路
-
寻找最短的可删除子串l,r初始值为0,n + 1 -- 字符串可能会被全部删除,也可能一个字符都不删除
-
使用map,记录上一次到达某位置时的字符串索引值 + 1,某位置是否到达过;
-
模拟机器人运行,若机器人运行到之前到过的位置,判断当前索引 -> 之前同位置索引的差值是否小于当前r - l,更新l,r的值;
-
最后判断l,r的值是否改变,输出“-1” or l 和 r;
-
map<pair<int,int>,int> m;
map<pair<int,int>,bool> vis;
pair<int,int> poi;//位置
string s;
cin >> t;
while(t--){
m.clear(),vis.clear();
poi.first = poi.second = 0;
cin >> n >> s;
l = 0,r = n + 1;
m[poi] = 0;//初始位置标记
vis[poi] = true;
for(int i=0;i<n;i++){
if(s[i] == ‘L‘) --poi.first;
else if(s[i] == ‘R‘) ++poi.first;
else if(s[i] == ‘U‘) ++poi.second;
else --poi.second;
if(vis[poi]){
if(i+1-m[poi] < (r-l)){
r = i+1;
l = m[poi]+1;//idx+1 - 上次到达位置 + 1 开始删除
}
m[poi] = i+1;
}else{
m[poi] = i+1;
vis[poi] = true;
}
}
if(l == 0 && r == n + 1) cout << "-1" << endl;
else cout << l << ‘ ‘ << r << endl;
}
D. Fight with Monsters
? n个怪物,每个怪物血量为hi,a和b的攻击力为a,b。a,b先对付第一个怪物,怪物受到攻击,血量 -= 相应攻击力,直到它死亡(hi <= 0)。然后,对付第二个、第三个...
? 给予怪物最后一击的人得一分,a先开始攻击且a攻击后可以跳过b继续攻击一次(最多跳k次),询问a的最大得分。
思路:
-
当怪物的血量 mod a + b 为0,看最后一轮时a需要多攻击几次(b / a上取整)
-
在怪物mod a + b后还存在正的血量,a尽可能的连击到怪物死亡(多攻击:剩余血量 / a 上取整 - 1次)
-
输入数据后,按照取模后的余数升序排列,贪心:排在前面的,尽可能多的由a击杀
cin >> n >> a >> b >> k;
vector<int> arr(n);
for(int i=0;i<n;i++){
cin >> arr[i];
arr[i] %= (a + b);
if(!arr[i]) arr[i] = a + b;//最后一轮
arr[i] = ((arr[i] + a - 1) / a) - 1;// a b a增加的次数上取整
}
sort(arr.begin(),arr.end());
for(int i = 0; i < n; i++){
if(k < arr[i]) break;
++ans;
k -= arr[i];
}
cout << ans;
E1. String Coloring (easy version)
? 一个由小字字母组成的字符串,所有元素均被涂上了黑色 or 白色,相邻且异色的字符可交换,字符串中的字符是否可以升序排列,如果可以,给出染色方案:0 1表示两种颜色
思路:
? 异色字符才可以交换,同色字符相对顺序不会发生改变 -- 即同色字符不递减。
贪心:s是否可分为两个不递减的子串
- 使用c1,c2分别记录两个同色字符串的最大字符,遍历字符串,若s[i] >= c1,加入c1所在子串;若 s[i] >= c2,加入c2所在子串;若s[i] 小于 c1,c2则在同色子串中出现递减 --> "NO"
//greedy
int n;
string s,ans;
char c1 ,c2;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> s;
c1 = c2 = ‘a‘;
ans = "";
for(int i = 0; i < s.length(); i++){
if(s[i] >= c1) c1 = s[i],ans += ‘0‘;//第一个子串,染色0
else if(s[i] >= c2) c2 = s[i],ans += ‘1‘;
else{
cout << "NO";
return 0;
}
}
cout << "YES" << endl << ans;
return 0;
}
E2. String Coloring (hard version)
? 与E1相比,字符的染色种类更多。需要输出染色种类最少的方案。
思路:
- 最多26种染色,依然可以贪心,增加一个字符串数组存储当前各字符串的最大字符,对s[i],进行E1中相同的步骤,不同的是:标记当前s[i]是否可以加入现有的字符串中,若不可以则增加一个字符串(题目保证最多26种染色,有解。),增加一个ans数组,在选择过程中存储答案即可。
const int kN = 2e5 + 5;
int n,idx,ans[kN];
bool flag;
char c[27];
string s;
//26个字符,最多26种染色
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> s;
for(int i = 1;i <= 26; i++) c[i] = ‘a‘;
idx = 1;
for(int i = 0; i < s.length(); i++){
flag = true;
for(int j = 1; j <= idx && flag; j++){
if(s[i] >= c[j]){
c[j] = s[i];
ans[i] = j;
flag = false;
}
}
if(flag){
c[++idx] = s[i];
ans[i] = idx;
}
}
cout << idx << endl ;
for(int i = 0; i < n; i++){
if(i) cout << ‘ ‘;
cout << ans[i];
}
return 0;
}
2.DP解法,待填......
以上是关于Codeforces Round #617(div3) A-E2题解的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #617 (Div. 3)
Codeforces Round #617 (Div. 3)
Codeforces Round #617 (Div. 3)
Codeforces Round #617 (Div. 3)