Codeforces Round 875 Div.2

5.29比赛记录

比赛结果:一道题都没写出来,尝试了前两道题,全部在测试点二超时

至此要注意的是在思考算法的同时尽量降低时间复杂度  不要局限在自己写的算法中,超时且无法继续优化后果断换思路 这次比赛前两道一眼看过去基本思路就全判断为全排列+判断 

一开始思路就有点歪,在比赛过程针对超时 想的是如何剪枝来优化 但是一直没什么思路 其实当时有一点关于A题解的思路 但是A题花时间太多不想继续了, 转战B 又是一眼全排列 此时本人脑子已经not found 直接本能秀技  这我刚学的深搜,回溯,并且当天上午还做了到深搜题,暴力深搜直接莽, 结果就是寄,又是测试点二超时,这就是不带脑子的下场。

做题一定要注意好数据范围 慎用暴力 超时超得你六亲不认 

Div.2 A

 

题目补充:ai + bi <= ai+1 + bi+1  翻译时少了一个等号

比赛思路:将1~n全部存储到数组中,利用next_permutation实现全排列,再循环每个排列找到符合条件的情况  耗时严重!!!

ac思路:利用可能相等的性质 a1 + b1 = a2 + b2 = a3 + b3 = ......C 常数

                bi = C - ai 由于每个ai都不同 因此得到的bi也一定不一样 

                题目要求ai bi 都属于1~n b(min) = 1 = C - a(max)        b(max) = C - a(min) = C - 1

                得出递推公式C = n + 1, bi = n + 1 - ai;        时间复杂度O(n)

比赛代码

#include<iostream>
#include<algorithm>
using namespace std;
int q[110], num[110];
int main(){
	int n;
	cin >> n;
	while(n --){
		int k; 
		cin >> k;
		for(int i = 0; i < k; i ++){
			scanf("%d", &q[i]);
			num[i] = i + 1;
		}
		do{
			int flag = 1;
			for(int i = 1; i < k; i ++){
				long long sum1 = num[i] + q[i], sum2 = num[i - 1] + q[i - 1];
				if(sum1 < sum2){
					flag = 0;
					break;
				}
			}
			if(flag){
				for(int i = 0; i < k; i ++)
					printf("%d ", num[i]);
				cout << endl;
				break;
			}
		}while(next_permutation(num, num + k));
	}
}

ac代码

#include<iostream>
using namespace std;
int main(){
	int n;
	cin >> n;
	while(n --){
		int k, num;
		cin >> k;
		for(int i = 0; i < k; i ++){
			cin >> num;
			cout << k + 1 - num << ' ';
		}
		cout << endl;
	}
}

Div2 B

比赛思路:利用递归回溯 枚举所有的数组c  枚举思想是每次从数组a取一个数放入c 递归下一层

                   回到这一层时取出数组a中的数 放入数组b中的数 再递归下一层。

                   每次递归到数组a取完 或数组b取完 或 同时取完 就计算最大相同子序列长度 更新到

                   全局变量mmax(切勿定义max 他是c++的一个库函数 不可做变量使用 编译会寄)

题解思路 首先将两个数组中各数字最大长度计算出来 双指针O(n)复杂度  在遍历所有数值 找到两个数组长度相加最大的作为答案  由于数组长度限制在2e5以内  输入数值在4e5以内 最后一步可直接遍历 不会超时

比赛代码

该代码依然存在问题  仅能实现部分排列

#include<iostream>
using namespace std;
const int N = 1e6;
int cnt[N], a[N], b[N];
int mmax;
void search(int z, int x, int y, int k){
	if(x == k && y == k){
		int length = 0, flag = 0;
		for(int i = 0, j = 1; i < k * 2 && j < k * 2;){
			if(cnt[i] == cnt[j])
				j ++;
			else{
				length = j - i;
				flag = 1;
				if(mmax < length)
					mmax = length;
				i = j;
				j ++;
			}
		}
		if(!flag)
			if(mmax < k * 2)	mmax = k * 2;
		return;
	}
	else if(x == k && y < k){
		for(int i = z; i <= k * 2; i ++)
			cnt[i] = b[y ++];
		int length = 0, flag = 0;
		for(int i = 0, j = 1; i < k * 2 && j < k * 2;){
			if(cnt[i] == cnt[j])
				j ++;
			else{
				length = j - i;
				flag = 1;
				if(mmax < length)
					mmax = length;
				i = j;
				j ++;
			}
		}
		if(!flag)
			if(mmax < k * 2)	mmax = k * 2;
		return;	
	}
	else if(x < k && y == k){
		for(int i = z; i <= k * 2; i ++)
			cnt[i] = a[x ++];
		int length = 0, flag = 0;
		for(int i = 0, j = 1; i < k * 2 && j < k * 2;){
			if(cnt[i] == cnt[j])
				j ++;
			else{
				length = j - i;
				flag = 1;
				if(mmax < length)
					mmax = length;
				i = j;
				j ++;
			}
		}
		if(!flag)
			if(mmax < k * 2)	mmax = k * 2;
		return;
	}
	else{
		cnt[z ++] = a[x ++];
		search(z, x, y, k);
		x --;
		z --;
		cnt[z ++] = b[y ++];
		search(z, x, y, k);
		y --;
		z --;
	}
	
}
int main(){
	int n;
	cin >> n;
	while(n --){
		int k;
		cin >> k;
		for(int i = 0; i < k; i ++)
			scanf("%d", &a[i]);
		for(int i = 0; i < k; i ++)
			scanf("%d", &b[i]);
		search(0, 0, 0, k);
		cout << mmax << endl;
		mmax = 0;
	}
}

ac代码

#include<iostream>
#include<vector>
using namespace std;
int main(){
	int n;
	cin >> n;
	while(n --){
		int k, mmax = 0;
		cin >> k;
		int a[k + 10], b[k + 10];
		for(int i = 0; i < k; i ++)
			scanf("%d", &a[i]);
		for(int i = 0; i < k; i ++)
			scanf("%d", &b[i]);
		int max1[k * 2 + 10] = {0}, max2[k * 2 + 10] = {0}, p = 0;
		for(int i = 1; i < k; i ++){
			if(a[i] != a[i - 1]){
				max1[a[i - 1]] = max(max1[a[i - 1]], i - p);
				p = i;
			}
		}
		max1[a[k - 1]] = max(max1[a[k - 1]], k - p);
		
		p = 0;
		for(int i = 1; i < k; i ++){
			if(b[i] != b[i - 1]){
				max2[b[i - 1]] = max(max2[b[i - 1]], i - p);
				p = i;
			}
		}
		max2[b[k - 1]] = max(max2[b[k - 1]], k - p);
		for(int i = 0; i <= k * 2; i ++){
			mmax = max(mmax, max1[i] + max2[i]);
		}
		cout << mmax << endl;
	}
}

以上为本次比赛记录

通过本次比赛,还是发现自己容易将题目的思考过程简单化, 代码实现复杂化。

对于题目只能简单的具象化, 比如B题,a + b 拼出数组 c 然后真就直接排列组合出c 在去找最大子长度 时间复杂度必定超时, 并且代码实现也更加复杂。

在做题时一定要多想一下,要多想, 找出这套流程本质的规律来实现,不能跟着题走。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值