Educational Codeforces Round 121 (Rated for Div. 2)A-D题解
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 121 (Rated for Div. 2)A-D题解相关的知识,希望对你有一定的参考价值。
- 博客主页: https://blog.csdn.net/qq_50285142
- 欢迎点赞👍收藏⭐️关注❤留言 📝 如有错误,敬请指正
- 🎈点击领取大量学习资源🎈
A. Equidistant Letters
一个字符串,要求让相同字母之间的距离相等,重新排列这些字母
找到相同的字母,相同的字母先排一遍,然后再按第一次排的顺序排一遍。
独有的字母就排在后面就行
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5+5;
int main()
int t;
scanf("%d",&t);
while(t--)
vector<int>cnt(26);
char s[55];
scanf("%s",s);
for(int i=0;i<strlen(s);i++)
cnt[s[i]-'a']++;
vector<int>a,b;
for(int i=0;i<26;i++)
if(cnt[i]==2) a.push_back(i);
else if(cnt[i]==1) b.push_back(i);
for(auto i : a) cout<<(char)(i+'a');
for(auto i : a) cout<<(char)(i+'a');
for(auto i : b) cout<<(char)(i+'a');
cout<<endl;
return 0;
B. Minor Reduction
一个数字,可以做一个操作:对相邻的两个数字做加和操作,加和的结果替代这两个数字,求可以形成的最大结果是多少?
考虑几种情况:
根据优先级进行:
- 最高:
两个相邻的数字相加结果为2
位,结果大于原来的两个相邻的数。遍历顺序为从前往后。
但是,此种情况不存在,最大也就9 + 9 =18
,18也还是小于99 - 中等:
相邻两个数相加结果位数为2
位,但是结果比原来小。遍历顺序为从后往前。因为要是前面的话一变小,高位会首先变小,数字肯定变得更小,要是从低位开始遍历,虽然变小,但是变化的是低位的数字,不至于变得更小。 - 最低:
两个相邻数字相加结果为1
位,结果肯定还是变小。遍历顺序为从前往后。相加虽然变成一位,但是该位的数字变得更大了,在高位相对不会变得更小。
该种情况可以简化:对第一个数字和第二个数字做加和运算即可
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5+5;
void solve()
string s;
cin>>s;
//中等
for(int i=s.size()-2;i>=0;i--)
int x = s[i]-'0' + s[i+1]-'0';
int cur = (s[i]-'0')*10 + s[i+1]-'0';
if(x <= cur && x>=10)
string t = to_string(x);
s[i] = t[0];
s[i+1] = t[1];
for(auto a:s) cout<<a;
cout<<endl;
return ;
//最低
int x = s[0]-'0' + s[1]-'0';
cout<<x;
for(int i=2;i<s.size();i++) cout<<s[i];
cout<<endl;
int main()
int t;
cin>>t;
while(t--) solve();
return 0;
C. Monsters And Spells
n
个怪兽,第i
个怪兽在 k i k_i ki秒出现,血量为 h i h_i hi.当前力量有两种变化方式:1.在原来攻击力的基础上加一 2.攻击力变为1
消耗值为每次的攻击力的和,求打完所有怪兽的最小消耗值
以由简到复杂的思路进行分析:
- 只有一个怪兽。它在
k
k
k秒出现,血量为
h
h
h,那么在
k
−
h
+
1
k-h+1
k−h+1秒时,攻击力要为
1
,即攻击力递增区间为 [ k − h + 1 , k ] [k-h+1,k] [k−h+1,k],总消耗值为 1 + 2 + . . . + h = h ( h + 1 ) 2 1+2+...+h=\\frach(h+1)2 1+2+...+h=2h(h+1) - 有两个怪兽。
- 如果两个怪兽出现互不干扰(就是后面出现的怪兽需要变为1的时间点在第一个怪兽出现时间点的后面),还是上面的计算方法,两个分别计算即可。
- 两个怪兽(设为
i
和j
, k i < k j k_i<k_j ki<kj)干扰了。 两个区间本来为 [ k i − h i + 1 , k i ] , [ k j − h j + 1 , k j ] [k_i-h_i+1,k_i],[k_j-h_j+1,k_j] [ki−hi+1,ki],[kj−hj+1,kj],出现干扰交叉也就是 k j − h j + 1 < = k i k_j-h_j+1<=k_i kj−hj+1<=ki了。本来这里应该变成1
的(这个位置如果是1的话见下),但是这又在i
的地方,这时攻击力必须为 h i h_i hi才能灭掉怪兽,所以后面必须递增下去,即 [ k j − h j + 1 , k j ] [k_j-h_j+1,k_j] [kj−hj+1,kj]区间是递增的,初值不再是1
,而是接着前面的进行递增变化。
漏了一点,当 k j − h j + 1 < = k i − h i + 1 k_j-h_j+1<=k_i-h_i+1 kj−hj+1<=ki−hi+1时,这个位置还可以是1
可以发现: 两个递增区间有交集,那么结果就是两个区间的并集,然后求总和。区间长度为len
,结果就为 l e n ( l e n + 1 ) 2 \\fraclen(len+1)2 2len(len+1)
- 三个怪兽。
不干扰还是各算各的。干扰的话就是求区间的并集,区间长度也可以求出,也可以算出结果。 - 总结下来:就是所有怪兽的攻击力递增区间求并集,对于每个合并后的大区间,攻击力是从1开始递增的。
那么这样就很好解决了,求出所有的区间,区间合并,求一下交集,同时记录结果即可。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5+5;
void solve()
int n;
cin>>n;
vector<pair<int,int>>p(n);
vector<int>k(n),h(n);
for(auto &i : k) cin>>i;
for(auto &i : h) cin>>i;
for(int i=0;i<n;i++)
p[i] = k[i]-h[i]+1,k[i];
sort(p.begin(),p.end());
ll res = 0 ;
ll l = 0,r = 0;
for(int i=0;i<n;i++)
if(p[i].first > r)
if(l && r) res += (r-l+1)*(r-l+2)/2;
l = p[i].first;
r = p[i].second;
else r = max((ll)p[i].second,r);
res += (r-l+1)*(r-l+2)/2;
cout<<res<<endl;
int main()
int t;
cin>>t;
while(t--) solve();
return 0;
D. Martial Arts Tournament
一系列数 w w w,确定两个边界
x
和y
,使w<x
的数有2的幂次个,使 x ≤ w < y x \\leq w \\lt y x≤w<y的数有2的幂次个,使 y ≤ w y \\leq w y≤w的数有2的幂次个,你可以添加任意数,求要满足上述条件需要添加的最少的个数
因为 n ≤ 2 e 5 n\\leq2e5 n≤2e5,所以我们记录数字出现的个数可以使用桶操作。
需要记录一下数字出现个数的前缀和和后缀和
pre[i]
:代表数字出现次数的和为i
次时,实际数字出现次数的前缀和
nxt[i]
:代表数字出现次数的和为i
次时,实际数字出现次数的后缀和
我们枚举左部分和右部分数字出现的次数,次数分别为i
和j
,次数以2次幂增长。
左部分需要添加的个数: i − p r e [ i ] i-pre[i] iEducational Codeforces Round 7 A
Educational Codeforces Round 7
Educational Codeforces Round 90
Educational Codeforces Round 33