ICode9

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

7月2日训练总结

2022-07-08 18:33:28  阅读:96  来源: 互联网

标签:总结 cout 训练 int cin else 数组 ans


900——1000 5道

A. Anti Light's Cell Guessing
题意大概是在一个行列确定的坐标系里,最少用几个点可以唯一确定一个点

思路就是判断行列的最小值是否为1,是1的话,最多一个点就可以确定,否则两个点即可。
注意:1*1的方格需要的点是0,故需要特判

解决代码:

void solve()
{
	int n, m;
	cin >> n >> m;
	if(n == m && n == 1) cout << 0 << endl;
	else 
		if(min(n, m) > 1) cout << 2 << endl;
		else cout << 1 << endl;
}

C. Minimum Extraction
题意是每次从数组中取出最小值,然后剩下的所有数全减去最小值,问最小值最大时为多少

思路:其实就是道差分,将数组从小到大排序后,建立差分数组,然后遍历找到最大值即可。

证明:
例如:3 2 -4 -2 0
排序后为 -4, -2, 0, 2 , 3
差分数组为2, 2, 2, 1
故其最大值为2

原因是每次减去最小值,是整个数组进行的,所以数组中两数的差值不变。故而两数的最小值也不变,排序后差分得到的数,都是本数变成最小数的最大值。而这即为所求

解决代码:

const int N = 200010, INF = 0x3f3f3f3f;
int a[N], b[N];

void solve()
{
	int n;
	cin >> n;
	for(int i = 1; i <= n; i++) cin >>a[i];
	sort(a + 1, a + 1 + n);
	int ans = -INF;
	for(int i = 1; i <= n; i++) b[i] = a[i] - a[i - 1], ans = max(ans, b[i]);
	
	cout << ans <<endl;
}

B. Odd Grasshopper
大意是给你初始位置,和移动次数,以你所在点为准,若是偶数,则往左跳,否则往右跳,跳的距离是跟着次数来的,比如第一次,跳一格,第二次跳两格,要求最后所在的位置是哪

通过观察可知,这个游戏的位置移动是周期性的,每跳4次就会回到初始位置。故而可以直接将次数mod4,然后模拟后续过程即可。但是我在写的时候将所有步骤全想清楚了,代码异常繁琐,也不需要分奇偶

解决代码:

void solve()
{
	int x, n;
	cin >> x >> n;
	int ans = 0;
	if(x % 2 == 0)
	{
		if(n % 4 == 0) ans = x;
		else if(n % 4 == 1)
		{
			ans = x - n;
		}
		else if(n % 4 == 2) ans = x + 1;
		else if(n % 4 == 3) ans = x + 1 + n;
	}
	else{
		if(n % 4 == 0) ans = x;
		else if(n % 4 == 1) ans = x + n;
		else if(n % 4 == 2) ans = x - 1;
		else if(n % 4 == 3) ans = x - 1 - n;
	}
	cout << ans <<endl;
}
 

A. AB Balance
题意是,给一串只含AB的字符串,输出修改后子串“AB”,与子串“BA”数量相等的字符串。

我写的时候思路是扫描一遍字符串,统计AB和BA出现的次数,等于返回原串,如果AB多于BA,如果第一个字符为a就改成b,如果最后一个字符为b则改成a,本意是减少一个ab。因为经过观察,ab和ba的数量之差不可能大于1。如果BA多于AB,则同理,反过来即可。

但看了官方题解之后,这题的规律其实就是:如果第一个字符和最后一个字符相等,那么AB和BA的数量一定相等,否则不等

解决代码:

void solve()
{
	string s;
	cin >> s;
	int len = s.size();
	int cnab = 0, cnba = 0;
	for(int i = 0; i < len - 1; i ++) 
	{
		if(s[i] == 'a' && s[i + 1] == 'b') cnab ++;
		if(s[i] == 'b' && s[i + 1] == 'a') cnba ++;
	}
	
	if(cnab == cnba) cout << s << endl;
	else {
		if(cnab > cnba)
		{
			if(s[0] == 'a') s[0] = 'b';
			else if(s[len - 1] == 'b') s[len - 1] = 'a';
		}
		else {
			if(s[0] == 'b') s[0] = 'a';
			else if(s[len - 1] == 'a') s[len - 1] = 'b';
		}
		cout << s << endl;
	}
}

B. Reverse Sort
题意是给一个01数组,然后选择其中递减的序列,排序翻转再依次放进被选择的位置,问需要几次,和每次选择用的下标是什么

自己写的时候没想到,后来看题解
思路是将数组排序后,观察现在和原来数组不同的地方,然后将下标存进vector中,一次即可解决
原理是现在和原来数组不同只可能是01,10两种情况,需要翻转的数列必然是10类的,符合题目要求,且10数量必然成对

解决代码:

void solve()
{
	int n;
	cin >> n;
	string s;
	cin >> s;
	string t;
	t = s;
	sort(t.begin(), t.end());
	if(s == t) cout << 0 << endl;
	else{
		cout << 1 <<endl;
		vector<int> v;
		for(int i = 0; i < s.size(); i ++) 
		{
			if(s[i] != t[i]) v.push_back(i + 1);
		}
		cout << v.size() << ' ';
		for(auto i : v) cout << i << ' ';
		cout << endl;
	}
}

1100——1200 3题

B. Odd Swap Sort
题意是选择两个相邻的数,如果他们相加为奇数,则可以交换,问是否能用若干次操作使数组以递增顺序排序

看的题解,刚开始想的用冒泡,可是超时了
思路:两个数相加为奇数,说明两个数的奇偶性不同。也就是说只有奇偶性不相同的才能交换,奇偶性相同的不能交换。
由此可以推出,如果奇偶性相同的数不是递增,那么必然不能完成,否则一定可以。

解决代码:

void solve()
{
	int n;
	cin >> n;
	vector<int> e, o;
	for(int i = 1; i <= n; i ++)
	{
		int x;
		cin >> x;
		if(x % 2) e.push_back(x);
		else o.push_back(x);
	}
	
	if(is_sorted(e.begin(), e.end()) && is_sorted(o.begin(), o.end())) puts("Yes");// is_sorted函数是用来判断是否数组有序的,有序true,无序false
	else puts("No");
	
}

C. Andrew and Stones
题意是选择三个下标a < b < c,每次可以从b所在点中取两个石头,一个放到a,一个放到c,当然前提是b要有两个石头,否则放不了。问是否可以通过一系列操作使石头全在数组第一个点和最后一个点中

看的题解
思路:假如有三个石头,第二个石头是奇数,则不可能,假如中间有若干个数,但都为1,则不可能。否则可能。因为每回都可以通过放石头使原来为奇数个石头的点变成偶数,从而放完石头

解决代码:

void solve()
{	
	int n;
	cin >> n;
	int maxv = -INF, ans = 0;
	for(int i = 1; i <= n; i ++) cin >> a[i];
	for(int i = 2; i < n; i ++) maxv = max(maxv, a[i]);
	if(maxv == 1 || n == 3 && a[2] % 2 == 1)
	{
		cout << -1 << endl;
		return ;
	}
	for(int i = 2; i < n; i ++) ans += (a[i] + 1) / 2;
	cout << ans << endl;
}
 

C. Differential Sorting

题意是给a < b < c三个点,问是否能通过将b - c所得值赋给a,来达到使整个数组递增的目的,如果可以输出需要几次和每次使用的下标

思路:如果从前向后遍历的话,c点的选取会很困难,所以从后先前遍历。c点开始是最后一个点,如果遇到比c更大的点,那么将之赋给c,b点是a点后面的一个点,这样可以保证a点被赋值后必然小于后面的点。
如果最后两个点是递减的那么肯定不可能,因为无法改变倒数第二个点的值。如果a点大于b点,且b点减去最大的c点都无法小于b点,那么说明a点无论如何都会大于b点,则不可能。

解决代码:

void solve()
{	
	int n;
	cin >> n;
	int cnt = 0;
	for(int i = 1; i <= n; i ++) cin >> a[i];
	if(a[n - 1] > a[n]) 
	{
		cout << -1 << endl;
		return ;
	}
	for(int i = n - 2, j = n - 1, k = n; i >= 1; i --, j--)
	{
		if(a[i] > a[j])
		{
			if(a[j] - a[k] > a[j])
			{
				cout << -1 << endl;
				return ;
			}
			else{
				a[i] = a[j] - a[k];
				ss[cnt].x = i, ss[cnt].y = j, ss[cnt].z = k;
				cnt ++;
			}
		}
		if(a[k] < a[j]) k = j;
	}
	cout << cnt << endl;
	for(int i = 0; i < cnt; i++) 
		cout << ss[i].x << ' ' << ss[i].y << ' ' << ss[i].z << endl;
}

总结:
900——1000的题目有时做的也磕磕绊绊,最后大都能想出来,但是时间耗费太长,思维不行。
1100——1200的题目看着都差不多,基本思路都有,但是如何优化需要好好想想,这种类型的题基本需要一点点算法和思维的敏捷,看能否找到最优解法,思维不够。

目前解决思路:多刷题,多总结。

标签:总结,cout,训练,int,cin,else,数组,ans
来源: https://www.cnblogs.com/lbzbk/p/16459343.html

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

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

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

ICode9版权所有