Codeforces Round #364 (Div. 2) 题解

题目链接:http://codeforces.com/contest/701


感想:以前打CF时,老是卡题,最后都很失败。这次虽然也卡了好多次,但是相对于以前来说,已经好多了。今天第一次做出第三题,虽然并不是很了不起,但是对自己来说是一个进步,好开森。要多多练习,更快速的解题,今天的前三道题,对自己来说,本来可以在45分钟之内就完成的,但最后还是花了一个多小时,以后要更快速地解决问题,加油。


A.思路:因为每个人手里的卡片值和最后要相等,并且保证有解且卡片数为偶数,所以最后每个人手里的卡片值和必为总值除以人数,即为平均数,然后从头到尾一一枚举,如果当前数没被访问,就从它后面再找一个没被访问的数,使得它们的和为平均数,输出答案并标记它们已被访问即可。


AC代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
int num[maxn];
bool vis[maxn];
int n;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	int sum = 0;
	for (int i=0; i<n; ++i){
		cin >> num[i];
		sum += num[i];
	}
	sum /= (n/2);
	for (int i=0; i<n; ++i)
		if (!vis[i]){
			vis[i] = true;
			for (int j=i+1; j<n; ++j)
				if (!vis[j] && num[i]+num[j]==sum){
					cout << i+1 << " " << j+1 << endl;
					vis[j] = true;
					break;
				}
		}
	return 0;
}

B.思路:只要当前一个旗子放在某一个位置,这个位置所在行列都会被攻击,那么只要统计那些行列被占据了即可。所以用两个集合维护行列被占据了几行几列(集合可以避免重复),假设行占据了x行,列占据了y列,那么当前还剩下n*n-x*n-(n-x)*y个位置,输出这个值即可。


AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n, m;
set<int> s1, s2;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n >> m;
	ll t = 1ll*n*n;
	int a, b, c=0;
	while (m--){
		cin >> a >> b;
		s1.insert(a);
		s2.insert(b);
		ll ans = t-1ll*s1.size()*n-1ll*(n-s1.size())*s2.size();
		if (c)
			cout << " ";
		cout << ans;
		++c;
	}
	cout << endl;
	return 0;
}

C.思路:先找到最后一个才开始计数的位置,假设为r,那么答案最可能的就是r+1。但是再想想看,如果最左边的种类计数大于1,那么就说明在当前区间中,去掉最左边的种类之后,对所有种类在该区间没影响,这样就可以一直缩短区间,结束后更新答案。是不是这就是解了呢?当然不是,因为右边还没有访问完的话,将区间向右移一个位置,这样这个区间里的该种类计数又多了1,那么接着执行上面的过程可能会使得区间更短而且满足条件,因此就这样每次移一个位置,直到不能移动为止,执行上面的过程,更新答案,最后的答案一定是最好的。


AC代码:

#include <bits/stdc++.h>
using namespace std;
int n;
string str;
map<char, int> m;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n >> str;
	int l=0, r=0;
	for (int i=0; i<n; ++i){
		if (m[str[i]] == 0)
			r = i;
		++m[str[i]];
	}
	for (int i=r; i<n; ++i)
		--m[str[i]];
	int ans = r-l+1;
	//cout << ans << endl;
	--r;
	while (++r < n){
		++m[str[r]];
		while (m[str[l]] > 1){
			--m[str[l]];
			++l;
		}
		ans = min(ans, r-l+1);
		//cout << ans << endl;
	}
	cout << ans << endl;
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值