Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals)

本文解析了三道ACM竞赛算法题目,包括简单的计数问题、基于二分搜索的时间问题及图论中的着色问题。介绍了每道题目的解决思路与核心算法实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A

这次的A比之前几次都简单、 因为不用想 hhhh

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <queue>
#include <string>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pill pair<int, int>
#define pb push_back
#define mk make_pair
#define REP(i, x, n)	for(int i = x; i < n; ++i)
const int qq = 1e5 + 10;
int num[qq];
int n;
int main(){
	scanf("%d", &n);
	int maxn = 0;
	int x;
	int cnt = 0;
	for(int i = 0; i < 2 * n; ++i){
		scanf("%d", &x);
		num[x]++;
		if(num[x] == 1)	cnt++;
		else if(num[x] == 2)	cnt--;
		maxn = max(maxn, cnt);
	}
	printf("%d\n", maxn);
	return 0;
}

B

这题是直接二分了、

题目中有句英文说明了, 不一定在整数点相遇, 很显然我们可以算在一定时间内每个人能达到的区间, n个人的区间有交集则true

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <queue>
#include <string>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define REP(i, x, n)	for(int i = x; i < n; ++i)
const int qq = 60000 + 10;
const double eps = 1e-7;
double x[qq], v[qq];
int n;
bool check(double k){
	double l = x[0] - k * v[0];
	double r = x[0] + k * v[0];
	for(int i = 1; i < n; ++i){
		double a = x[i] - k * v[i];
		double b = x[i] + k * v[i];
		if(b < l)	return false;
		if(a > r)	return false;
		l = max(l, a);
		r = min(r, b);
	}
	return true;
}
int main(){
	scanf("%d", &n);
	for(int i = 0; i < n; ++i){
		scanf("%lf", x + i);
	}
	for(int i = 0; i < n; ++i){
		scanf("%lf", v + i);
	}
	double l = 0, r = 1000000000.;
	while(l + eps < r){
		double mid = (l + r) / 2.;
		if(check(mid))	r = mid - eps;
		else	l = mid + eps;
	}
	printf("%.8lf\n", l);
	return 0;
}

C

题意:如果a、b、c之间a能到b 且 b能到c, 则a b c三个顶点不同色, 求每个点的颜色编号以及需要最小的颜色数

我们可以发现需要最少的颜色数是等于图中顶点的度数最大的那个去加上1, 就是k值

然后处理每一个点的颜色, 以1为根节点, 对于每一个有父节节点的顶点,我们可以直接对它的孩子节点着色, 着色方式是用map统计当前没用过的颜色

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <queue>
#include <string>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define REP(i, x, n)	for(int i = x; i < n; ++i)
const int qq = 2e5 + 10;
int deg[qq];
vector<int> vt[qq];
int color[qq];
int vis[qq];
int n;
map<int, bool> mp;
void dfs(int rt, int a, int b){
	mp.clear();
	int sz = (int)vt[rt].size();
	mp[a] = true, mp[b] = true;
	int cnt = 1;
	while(mp[cnt] == true)	cnt++;
	for(int j = 0; j < sz; ++j)if(!vis[vt[rt][j]]){
		int v = vt[rt][j];
		if(!color[v]){
			color[v] = cnt;
			mp[cnt] = true;
			while(mp[cnt] == true)	cnt++;
		}
	}
	for(int j = 0; j < sz; ++j)if(!vis[vt[rt][j]]){
		int v = vt[rt][j];
		vis[v] = 1;
		dfs(v, b, color[v]);
	}
}
int main(){
	scanf("%d", &n);
	int a, b;
	for(int i = 1; i < n; ++i){
		scanf("%d%d", &a, &b);
		deg[a]++, deg[b]++;
		vt[a].pb(b);
		vt[b].pb(a);
	}
	int k = 0;
	for(int i = 1; i <= n; ++i)
		k = max(k, deg[i] + 1);
	int cnt = 2;
	vis[1] = 1;
	color[1] = 1;
	for(int i = 0; i < (int)vt[1].size(); ++i){
		color[vt[1][i]] = cnt++;
		vis[vt[1][i]] = 1;
	}
	for(int i = 0; i < (int)vt[1].size(); ++i){
		dfs(vt[1][i], color[1], color[vt[1][i]]);
	}
	printf("%d\n", k);
	for(int i = 1; i <= n; ++i)
		printf("%d ", color[i]);
	puts("");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值