Codeforces刷题


前言

刷题结合知识点学习——数论,字符串处理,搜索,DP,计算几何,规律题。
各种错误(堆栈溢出,段错误…)
7.18早上,刷不下去了,整理一下。刷题刷到心态爆炸。

一、Codeforces:

1.A. Find The Array

题目大意: 定义一个“beautiful”数组,满足里头的元素要么为1,要么ai-1或者ai-2在数组中存在。输入数组的总和s,输出数组最小的大小其元素总和等于s,数组需为“beautiful”数组。

大致思路:s不大,0<=s<=5000,这里数组里全部取奇数和全部取偶数是一样的,都满足“beautiful”的条件,这里以奇数为例:前n项奇数的和为:n*n,找到大于等于s的最小n,即为答案。(至于这里为什么是:找到大于等于s的最小n,原因在于若找到一个n,n×n<s且(n+1)×(n+1)>s则总可在n的基础上补上一个偶数a,满足n×n+a==s,即n+1个数

AC的代码

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int s[100];

// 这里先打表,到时候直接查询就行了.
void init(){
    
    
	for(int i=1;i<=73;i++){
    
    
		s[i] = i*i;
	}
}

int main()
{
    
    
	init();
//	for(int i=1;i<=72;i++){
    
    
//		cout << s[i] << endl;
//	}
	int t;
	scanf("%d",&t);
	int a,ans;
	while(t--){
    
    
		ans = 0;
		scanf("%d",&a);
		
		for(int i=1;i<=72;i++){
    
    
			if(s[i]>=a){
    
    
				ans += i;
				break;
			}
		}
		
		printf("%d\n",ans);
	}
	
	return 0;
} 

2.B. Maximum Cost Deletion

题目大意:给定一个01串,每次删除相同的子串(0串或1串),每删除一次,计算一次分数a×l+b(l为删除的长度),给定a,b计算最大分数。

大致思路:分情况讨论:当b>=0时,ans=n*(a+b);当b<0时,统计0子串和1子串的个数,ans = na + b(min(cnt0,cnt1)+1)。

AC的代码

#include <iostream>
#include <cstdio>

using namespace std;

int main()
{
    
    
	long long ans;
	int t;
	scanf("%d",&t);
	int n,a,b,cnt0,cnt1;
	char book = 'w';
	string s;
	while(t--){
    
    
		ans = 0;
		scanf("%d%d%d",&n,&a,&b);
		cin >> s;
		
		if(b>=0){
    
    
			ans = n*(a+b);
		}else{
    
    
			book = -1;
			cnt0 = 0,cnt1 = 0;
			for(int i=0;s[i];i++){
    
    
				if(s[i]!=book){
    
    
					if(s[i]=='0'){
    
    
						cnt0++;
					}else{
    
    
						cnt1++;
					}
					
					book = s[i];
				}
			}
			
			ans = n*a + b*(min(cnt0,cnt1)+1);
		}
		
		printf("%d\n",ans);
	}
	
	return 0;
}

3.C. Manhattan Subarrays

题目大意:
定义曼哈顿距离:d(p,q)=|xp−xq|+|yp−yq|;
定义good数组:不可能挑出三个元素(下标为p,q,r)使d(p,r)=d(p,q)+d(q,r)。注:数组大小为1,2的子数组均为good数组。
给定一个数组,计算good子数组的个数。

大致思路:
第一次感觉样例有问题,反复读题,一直没找出问题,直到第二天再读题,还是没有看出什么问题,直到刚刚才发现问题所在:取出的子元素必须是连续的。
找出规律,good数组的大小最大为4。连续的话,从左向右取就好了。ans初始先统计大小为1和2的子数组的个数。

AC的代码

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int a[300010];

int main()
{
    
    
	int t,n;
	scanf("%d",&t);
	while(t--){
    
    
		scanf("%d",&n);
		
		for(int i=0;i<n;i++){
    
    
			scanf("%d",&a[i]);
		}
		
		int res = 2*n - 1;
		
		for(int i=1;i<n-1;i++){
    
    
			if(a[i]>a[i-1]&&a[i]>a[i+1]){
    
    
//				cout << a[i-1] << " " << a[i] << " " << a[i+1] << endl; 
				
				res++;
				
				if(n>i+2&&a[i-1]>a[i+1]&&a[i]>a[i+2]&&a[i+1]<a[i+2]){
    
    
				
//					cout << a[i-1] << " " << a[i] << " " << a[i+1] << " " << a[i+2] << endl; 
					res++;
				}
			}
			if(a[i]<a[i-1]&&a[i]<a[i+1]){
    
    
//				cout << a[i-1] << " " << a[i] << " " << a[i+1] << endl; 
				
				res++;
				
				if(n>i+2&&a[i-1]<a[i+1]&&a[i]<a[i+2]&&a[i+1]>a[i+2]){
    
    
				
//					cout << a[i-1] << " " << a[i] << " " << a[i+1] << " " << a[i+2] << endl; 
					res++;
				}
			}
		}
		
		printf("%d\n",res);
	}
	
	return 0;
}

4.B. AquaMoon and Stolen String

题目大意:
输入n和m,n表示n个字符串,n为奇数,m表示字符串的长度
之后输入n个字符串,表示原字符串;再输入n-1个字符串,表示交换后的字符串(两两交换,只有一个串没被交换过)
找出那个没被交换过的字符串。

大致思路:
1.一开始思路错误:借用了桶排序的思想;即把原始字符串的每个字符的个数都统计出来,再减去交换过的字符串的每个字符的数量。但问题在于,答案让输出没被交换过的串,这样做无形中打乱的未被交换过的串的顺序,使其按照字典序输出了。
2.进行思路修正后,利用位运算 ^ 的思想,a ^ b ^ a = b ,以字符为一个单位的话,不管进行如何的交换,交换过的字符都会出现两次或者偶数次,没交换过的都会出现奇数次或一次。这里把字符映射为数字进行处理。

AC的代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

typedef unsigned long long ull;

ull a[100010];
char s[100010];

int main()
{
    
    
	int t;
	cin >> t;
	int n,m;
	while(t--){
    
    
		memset(a,0,sizeof(a));
		
		scanf("%d%d",&n,&m);
		
		for(int i=1;i<=n;i++){
    
    
			scanf(" %s",s);
			
			for(int j=0;j<m;j++)
				a[j] += s[j] - 'a' + 1;
		}
		
		for(int i=1;i<n;i++){
    
    
			scanf(" %s",s);
			
			for(int j=0;j<m;j++)
				a[j] -= s[j] - 'a' + 1;
		}
		
		for(int i=0;i<m;i++){
    
    
			printf("%c",(char)(a[i]-1+'a'));
		}
		printf("\n");
	}
	
	
	return 0;
}

5.A. AquaMoon and Two Arrays

题目大意:
定义一种操作:取i,j,令ai-1,aj+1;
给定两个数组a,b;问a能否通过有限次操作到达b,若能输出操作次数m及m次操作,否则输出-1.

大致思路:
水题飘过,若两个数组的和相等,则一定能到达,反之不能。
具体实行:计算a,b数组每个位置的差值,存到c数组里头;每次取c[k]<0输出为j,后c[k]++;c[p]>0输出为i,c[p]–,直到每个元素都为0为止.

AC的代码:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int a[105],b[105],c[105];

int main()
{
    
    
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	int t,n;
	cin >> t;
	int sum1,sum2,ans;
	while(t--){
    
    
		ans = 0;
		
		cin >> n;
		sum1 = 0,sum2 = 0;
		
		for(int i=1;i<=n;i++){
    
    
			cin >> a[i];
			
			sum1 += a[i];
		}
		for(int i=1;i<=n;i++){
    
    
			cin >> b[i];
			c[i] = a[i] - b[i];
			
			sum2 += b[i];
		}
		
		for(int i=1;i<=n;i++){
    
    
			if(c[i]>0){
    
    
				ans += c[i];
			}
		}
		
		int j;
		if(sum1!=sum2){
    
    
			cout << "-1" << endl;
		}else{
    
    
			cout << ans << endl;
			
			for(int i=1;i<=n;i++){
    
    
				while(c[i]>0){
    
    
					for(j=1;j<=n;j++){
    
    
						if(c[j]<0)
							break;
					}
					cout << i << " " << j << endl;
					c[i]--;
					c[j]++;
				}
			}
		}
	}
	
	
	return 0;
}

6. AquaMoon and Strange Sort

题目大意:
给定一个数组,每个元素都有一个方向(开始均向右)。通过交换相邻两个数组元素,使数组构成一个非递减序列,且方向向右。可以则输出YES,否则输出NO。

大致思路:倘若交换两个元素,则这两个元素必交换偶数次。
先sort一下,后计算开始每个元素距离目标位置的距离。从右往左开始计算距离ds,判断ds的奇偶性。
每个元素相距目标位置距离都为0或者偶数个单位时输出YES,否则输出NO。

AC的代码:

// 每个元素相距目标位置距离都为0或者偶数个单位时输出YES,否则输出NO。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 100010;
int a[N],b[N];
int p[N][2];

int main()
{
    
    
	int t,n;
	scanf("%d",&t); 
	while(t--){
    
    
		memset(p,0,sizeof(p));
		scanf("%d",&n);
		
		for(int i=0;i<n;i++){
    
    
			scanf("%d",&a[i]);
			b[i] = a[i];
		}
			
		sort(b,b+n);
		
		for(int i=0;i<n;i++){
    
    
			p[a[i]][i&1]--;
			
			cout << "a[i]=" << a[i] << " p[a[i]][i&1]=" << p[a[i]][i&1] << endl; 
		}
		
		int flag = 1;
		for(int i=0;i<n;i++){
    
    
			if(p[b[i]][i&1]<0) p[b[i]][i&1]++;          	
			//原来位置和目标位置的距离为偶数时i&1值相同 
			else flag = 0;
		}
		
		puts(flag?"YES":"NO");
	}
	
	return 0;
} 

总结:

先写这么多吧,下午写在牛客刷的题。

猜你喜欢

转载自blog.csdn.net/m0_50435987/article/details/118874588