0
点赞
收藏
分享

微信扫一扫

Educational Codeforces Round 121 (Rated for Div. 2)A-C题解

老王420 2022-01-20 阅读 59

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


以由简到复杂的思路进行分析:

  • 只有一个怪兽。它在 k k k秒出现,血量为 h h h,那么在 k − h + 1 k-h+1 kh+1秒时,攻击力要为1,即攻击力递增区间为 [ k − h + 1 , k ] [k-h+1,k] [kh+1,k],总消耗值为 1 + 2 + . . . + h = h ( h + 1 ) 2 1+2+...+h=\frac{h(h+1)}{2} 1+2+...+h=2h(h+1)
  • 有两个怪兽。
    • 如果两个怪兽出现互不干扰(就是后面出现的怪兽需要变为1的时间点在第一个怪兽出现时间点的后面),还是上面的计算方法,两个分别计算即可。
    • 两个怪兽(设为ij, 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] [kihi+1,ki],[kjhj+1,kj],出现干扰交叉也就是 k j − h j + 1 < = k i k_j-h_j+1<=k_i kjhj+1<=ki了。本来这里应该变成1的(这个位置如果是1的话见下),但是这又在i的地方,这时攻击力必须为 h i h_i hi才能灭掉怪兽,所以后面必须递增下去,即 [ k j − h j + 1 , k j ] [k_j-h_j+1,k_j] [kjhj+1,kj]区间是递增的,初值不再是1,而是接着前面的进行递增变化。

      漏了一点,当 k j − h j + 1 < = k i − h i + 1 k_j-h_j+1<=k_i-h_i+1 kjhj+1<=kihi+1时,这个位置还可以是1
      可以发现: 两个递增区间有交集,那么结果就是两个区间的并集,然后求总和。区间长度为len,结果就为 l e n ( l e n + 1 ) 2 \frac{len(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;
 } 

往期优质文章推荐

领取大量学习资源

举报

相关推荐

0 条评论