ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #805 (Div. 3) A——E补题

2022-07-12 22:00:59  阅读:167  来源: 互联网

标签:ch int Codeforces cin ++ 补题 Div find mp


A. Round Down the Price

题意: 给一个数n,要求找到离这个数最近的10的幂次。然后输出两者差值

思路:看了下数据范围,1e9,直接枚举就好了。从1e9开始,如果大于n就除10,否则就停止,相减即可

解决代码:

void solve()
{	
	int n;
	cin >> n;
	int a = 1e9;
	while(a > n)
	{
		a /= 10;
	}
	cout << n - a << endl;
}

B. Polycarp Writes a String from Memory

题意:给出一个单词,从前向后记,每次可以记住三种字母,问多少次可以记完整个单词。

思路:用set遍历字符串,尽可能的向后读。当set即将存进第四种字母的时候,说明set中已经有了3种字母,且已经达到了最大程度的存储,此时,ans++,将set清空,然后再存进第四种字母。

解决代码:

void solve()
{	
	string s;
	cin >>s;
	int len = s.size();
	int cnt = 0;
	set<char> se;
	for(int i = 0; i < len; i ++) 
	{
		se.insert(s[i]);
		if(se.size() == 4)
		{
			se.clear();
			se.insert(s[i]);
			cnt ++;
		}
	}
	if(se.size()) cnt ++;
	cout << cnt <<endl;
}

C. Train and Queries

题意: 给出一组数字,位于前面的数字可以到达后面的数字,但后面的不能到达前面的,数字可以重复。给出k次询问,每次给出a, b,问a是否能到达b。

一开始被吓到了,以为是邻接表并查集之类的。没想到只是水平太差了。基本没涉及到算法层次。

思路:用map存储每个数字出现的下标。然后在查询的时候访问是否a的第一个下标小于b的最后一个下标,若是yes,不是no。

解决代码:

void solve()
{	
	int n, k;
	cin >> n >> k;
	map<int, vector<int>> mp;
	for(int i = 1; i <= n; i++)
	{
		int x;
		cin >>x;
		mp[x].push_back(i);
	}
	while(k --)
	{
		int a, b;
		cin >> a>> b;
		if(mp.find(a) == mp.end() || mp.find(b) == mp.end())  //特判,当a或者b没出现在数组中,也是no
		{
			puts("No");
			continue;
		}
		auto t = mp[a][0];
		if(t < mp[b].back()) puts("Yes");
		else puts("No");
	}
}

D. Not a Cheap String

题意:给出一个字符串,和一个数p。字母a——z分别对应价值1——26,问最少删除几个字符可以使字符串的总价值小于等于p。

思路:贪心即可。存储字符串里每个字符出现的次数,然后从大到小减去即可。当小于等于p时停止。然后输出子串的时候直接看存储数组中是否还有这个字符,没有就不输出,有就输出。

解决代码:


int ch[30];

void solve()
{	
	string s;
	cin >> s;
	int p;
	cin >> p;
	int v = 0;
	memset(ch, 0, sizeof(ch));
	for(int i = 0; i < s.size(); i ++)
	{
		int t = s[i] - 'a' + 1;
		ch[t] ++;
		v += t;
	}
	if(v == p)
	{
		cout << s <<endl;
		return ;
	}
	for(int i = 26; i >= 1; i--)
	{
		if(ch[i])
		{
			while(ch[i] && v > p)
			{
				v -= i;
				ch[i] --;
			}
		}
	}
	for(int i = 0; i < s.size(); i ++)
	{
		int t = s[i] - 'a' + 1;
		if(ch[t]) cout << s[i], ch[t] --;
	}
	cout << endl;
}

E. Split Into Two Sets

题意:给出n张带有两个数字的牌,问是否能将之完全分为两份。每份都含有1——n所有的数字且不重复。(n是偶数)

写的时候没想到,天真就以为两个set就能写。写了半天发现不对劲,后来补题才知道是二分图。

思路:我看的解法是用并查集求连通块大小的思路写的。他所使用的方法是将每次输入的两个数放入一个集合里,然后如果两组数据中有交叉部分,则此集合的大小必然不是偶数。也就是有奇数环,我们知道,有奇数环必然不是二分图。而如果每个数出现的次数不等于2次,那么说明也必然不能完美分成两个集合。

解决代码:原作者题解网址

int p[N], sz[N], cnt[N];
 
int find(int x)
{
	if(x != p[x]) p[x] = find(p[x]);
	return p[x];
}
 
void merge(int x, int y)
{
	int a = find(x), b = find(y);
	if(a != b)
	{
		p[a] = b;
		sz[b] += sz[a];
	}
}
 
void solve()
{	
	int n;
	cin >> n;
	
	for(int i = 1; i <= n; i ++) p[i] = i, cnt[i] = 0, sz[i] = 1;
	
	for(int i = 1; i <= n; i++) 
	{
		int a, b;
		cin >> a >> b;
		merge(a, b);
		cnt[a] ++, cnt[b] ++;
	}
	
	for(int i = 1; i <= n; i ++)
	{
		if(cnt[i] != 2)
		{
			puts("No");
			return ;
		}
	}
	
	for(int i = 1; i <= n; i ++)
	{
		if(i != p[i]) continue;
		if(sz[find(i)] % 2 == 1) 
		{
			puts("No");
			return ;
		}
	}
	
	puts("Yes");
}

总结:这场打的很水,虽说写了四道题,但是后两题a的很慢,且还有一道在重测的时候被官方样例hack了。
问题在于:
(1)题目没读清楚就开始盲目解题,第四题就是,以为必须等于p,还以为要用dp写,后面才发现就是个贪心,几分钟就可以解决,结果放了一个小时才去写。
(2)思维还是不够灵活,第三题其实也是自己写出来的,后来也就差一步,没用O(n)做法被刷了。但是解决速度较慢,没有快速能过想到。
(3)算法知识基本没有掌握,很多题目都是知道大概解法,但是不会写。要多去温习以前学过的知识,然后多了解不知道的知识。

标签:ch,int,Codeforces,cin,++,补题,Div,find,mp
来源: https://www.cnblogs.com/lbzbk/p/16471932.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有