Codeforces Round #632 (Div. 2)A-C

题目传送门

A. Little Artem

本题的题意大致为给你一个nxm大小的矩阵,要求你将其中的格子涂成白色或者黑色,定义一个白色格子周围如果有至少一个黑色的格子,那么这个白色的格子为好格子,黑色格子亦是如此,要求黑色好格子的数量为白色好格子数量+1
这题乍一看好像很难,但是题目有 2<=n,m,这就意味着,我们总是可以构造出一个矩阵,其一个角落涂成白色,其它的都涂成黑色。不难证明,因为只有2个黑格子与角落的白格子相邻,所以永远满足。
主要代码:

int t;cin>>t;
	while(t--){
		int n,m;cin>>n>>m;
		int fi =1;
		for(int i = 0;i < n;++i){
			for(int j = 0;j < m;++j){
				if(fi){cout<<'W';fi=0;}//仅最左上角涂白,其它全为黑
				else cout<<'B';
			}
			cout<<'\n';
		}
	}

B. Kind Anton

本题的题意大致为给你一个长为n的数组a,a中的元素只有{0,1,-1},可以进行如下操作0或者多次:

1、取a数组两个数 a i a_{i} ai, a j a_{j} aj(0<=i<j<n),
2、 a j a_{j} aj= a i a_{i} ai+ a j a_{j} aj

问是否能得到目标数组b。
因为 i<j,那就不难想到, b i b_{i} bi< a i a_{i} ai,只要判断 a i a_{i} ai前面有没有-1;当 a i a_{i} ai< b i b_{i} bi,只要判断 a i a_{i} ai前有没有1;而 a i a_{i} ai= b i b_{i} bi的时候不用判断。
主要代码:

const int N = 1e5+5;
int a[N],b[N];
int T;cin>>T;
	while(T--){
		bool flag = true;
		bool p1 = false,p2 = false;//分别用于判断这个数前面是否有1,-1
		int n;cin>>n;
		for(int i = 0;i < n;++i)cin>>a[i];
		for(int i = 0;i < n;++i)cin>>b[i];
		for(int i = 0;i < n;++i){
			if(a[i]<b[i]&&!p1)flag = false;//当a[i]<b[i],并且a[i]前没有1,输出NO
			else if(a[i]>b[i]&&!p2)flag = false;//当a[i]>b[i],并且a[i]前没有-1,输出NO
			if(a[i]==1)p1 = true;
			else if(a[i]==-1)p2 = true;
		}
		if(flag)cout<<"YES\n";
		else cout<<"NO\n";
	}

C. Eugene and an array

这题的题意很绕,刚开始都绕晕了,大致意思可以理解为,给你一个长为n的数组,要你求这个数组有多少个好的子数组(连续的),一个好的子数组定义为:这个子数组的所有子数组的各自的元素之和不为0
那么很明显,既然是要求和,那必然就有区间操作,但这里用线段树硬搞很费时间,用前缀和处理即可,前缀和相同的就不是好的子数组,那么包含这个子数组的子数组也不是好的子数组,那么问题就可以转为求,不包含这些前缀和相同的的下标构成的大区间的区间,我们只需要在遍历的时候不断地更新重复区间的左端点, ∑ 1 n \sum_1^n 1n(i - 左端点 -1),即为要求的答案.。统计重复出现的前缀和用map即可最好不要用unordermap,因为一卡哈希冲突就o(n)寻访了,而CF卡哈希冲突是常事。
主要代码:

const int N = 2e5+5;
int a[N];
map<ll,int>mp;
	int n;cin>>n;
	mp[0] = 0;//很重要,初始的0的下标即为0
	long long qz = 0,ans = 0;
	int pos = -1,x;//左端点从-1开始,这样区间数就是下标
	for(int i = 0;i <= n;++i){
		cin>>x;
		qz+=x;
		if(mp.count(qz))pos = max(pos,mp[qz]);//更新左端点
		ans += i - pos - 1;
		mp[qz] = i;
	}
	cout<<ans<<'\n';

C本人想法就是求区间,如果有更好的想法欢迎留言OWO

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值