Educational Codeforces Round 121 (Rated for Div. 2)A-C problem solution

Posted by mooshuligan on Sat, 22 Jan 2022 12:52:07 +0100

A. Equidistant Letters

A string that requires equal distances between the same letters and rearranges them

Find the same letters, arrange the same letters first, and then arrange them in the order of the first time.
The unique letters are just behind

#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

A number can do an operation: add two adjacent numbers, and the result of the addition replaces the two numbers. What is the maximum result that can be formed?

Consider several situations:
According to priority:

• highest:
The addition result of two adjacent numbers is 2 bits, and the result is greater than the original two adjacent numbers. The traversal order is from front to back.
However, this situation does not exist. The maximum is 9 + 9 = 18, and 18 is still less than 99
• Medium:
The number of digits of the addition result of two adjacent numbers is 2, but the result is smaller than the original. The traversal order is from back to front. Because if the previous words become smaller, the high order will become smaller first, and the number must become smaller. If you traverse from the low order, although it becomes smaller, the low order number will not become smaller.
• Minimum:
The result of adding two adjacent numbers is 1 bit, and the result must be smaller. The traversal order is from front to back. Although the addition becomes one bit, the number of this bit becomes larger and will not become smaller in the high order.

This situation can be simplified: add the first number and the second number
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N = 1e5+5;

void solve()
{
string s;
cin>>s;
//secondary
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 ;
}
}
//minimum
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 monsters, i monster in k i k_i ki appears in ， seconds, and the blood volume is h i h_i hi​. There are two ways to change the current power: 1 Add 1.2 to the original attack power Attack power becomes 1
The consumption value is the sum of the attack power of each time. Find the minimum consumption value of all monsters

Analyze from simple to complex:

• There's only one monster. It's in k k Appears in k seconds, and the blood volume is h h h. So in k − h + 1 k-h+1 When k − H + 1s, the attack power should be 1, that is, the increasing range of attack power is [ k − h + 1 , k ] [k-h+1,k] [K − h+1,k], the total consumption value is 1 + 2 + . . . + h = h ( h + 1 ) 2 1+2+...+h=\frac{h(h+1)}{2} 1+2+...+h=2h(h+1)​
• There are two monsters.
• If two monsters do not interfere with each other (that is, the time point at which the later monster needs to become 1 is behind the time point at which the first monster appears), the above calculation method can be calculated separately.
• Two monsters (set to i and j, k i < k j k_i<k_j ki < kJ) interferes. The two intervals were originally [ 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], interference crossing occurs, that is k j − h j + 1 < = k i k_j-h_j+1<=k_i kj − hj + 1 < = ki. It should have become 1 here (see below if this position is 1), but it is at i. at this time, the attack power must be h i h_i hi ， can kill the monster, so it must increase in the future, that is [ k j − h j + 1 , k j ] [k_j-h_j+1,k_j] The interval [kj − hj + 1,kj] is incremented, and the initial value is no longer 1, but is incremented by the previous.

A little missing, when k j − h j + 1 < = k i − h i + 1 k_j-h_j+1<=k_i-h_i+1 When kj − hj + 1 < = ki − hi + 1, this position can also be 1
It can be found that if two increasing intervals intersect, the result is the union of the two intervals, and then sum them. If the interval length is len, the result is l e n ( l e n + 1 ) 2 \frac{len(len+1)}{2} 2len(len+1)​
• Three monsters.
It's still their own business if they don't interfere. Interference is to find the union of intervals, and the interval length can also be calculated, and the result can also be calculated.
• To sum up: it is the union of the attack power increasing intervals of all monsters. For each combined large interval, the attack power increases from 1.

So this is a good solution. Find all the intervals, merge the intervals, find the intersection, and record the results at the same time.

#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;
}


Recommendation of previous high-quality articles

Receive a large number of learning resources