Codeforces Round #661 (Div. 3) A、B、C、D、E1 题解

1399 A. Remove Smallest

题意:每次选择两个相差绝对值不大于1的数,随机删掉一个。问是否可以通过上述操作,使得数组中只剩下一个元素。

思路:从小到大排个序。判断相邻数之间的差是否有大于1的,有的话则不行。反之则可以。

#include
using namespace std;
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
 
 
int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
 
	while (t--) {
		int n;
		cin >> n;
		vector<int> v(n);
		for (auto& val : v) {
			cin >> val;
		}
		int flag = 1;
		sort(v.begin(), v.end());
		int i;
		for (i = v.size() - 1; i > 0; i--) {
			if (v[i] - v[i - 1] > 1) {
				flag = 0;
				break;
			}
		}
		if (flag)cout << "YES" << endl;
		else cout << "NO" << endl;
		
	}
	return 0;
}

1399 B. Gifts Fixing

题意:有n个礼物,每个礼物里面有a个糖和b个橘子。可以进行三种不同的操作。

  • 选择一份礼物中的糖,然后吃掉一个。

  • 选择一份礼物中的橘子,然后吃掉一个。

  • 选择一份礼物中的糖和橘子,吃掉一个。

最后要是每份礼物中的糖数量都相等, 橘子数量都相等。但糖和橘子的数量都相等。且数量不能小于等于0。

思路:分别找出糖和橘子的最小数量。因为要是所有的糖数量相等,橘子数量相等,那么只能都变成最小的。然后遍历所有礼物。每个礼物的操作数为max(糖变成最小数量的操作数,橘子变成数量最小的操作数)

#include
using namespace std;
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
 
bool isPrime(long long x) {
	if (x <= 1)return false;
	if (x == 2)return true;
	if (x % 2 == 0)return false;
	long long m = sqrt(x);
	for (long long i = 3; i <= m; i += 2) {
		if (x % i == 0)return false;
	}
	return true;
}
 
long long gcd(long long m, long long n) {
	return m % n == 0 ? n : gcd(n, m % n);
}
 
unordered_map<long long, int> mmid;
 
long long fib[90];
 
void initFib() {
	fib[0] = fib[1] = 1;
	mmid[1] = 1;
	int i;
	for (i = 2; i < 90; i++) {
		fib[i] = fib[i - 1] + fib[i - 2];
		mmid[fib[i]] = 1;
	}
}
 
int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
 
	while (t--) {
		int n;
		cin >> n;
		vector<pii> v(n);
		int a_min = INT_MAX;
		int b_min = INT_MAX;
		for (auto& val : v) {
			cin >> val.first;
			a_min = min(a_min, val.first);
		}
		for (auto& val : v) {
			cin >> val.second;
			b_min = min(b_min, val.second);
		}
		long long ans = 0;
		for (auto& val : v) {
			int tmp1 = val.first - a_min;
			int tmp2 = val.second - b_min;
			ans = ans + max(tmp1, tmp2);
		}
		cout << ans << endl;
		
	}
	return 0;
}

1399 C. Boats Competition

题意:给n个数,问两两组成一个一队,并且所有的队中两数之和要相等。最多可以选择多少队。

思路:暴力。先用map保存每个数出现的次数。然后枚举所有可能是sum。

#include
using namespace std;
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
const long long INF = 1e15;
const int maxn = 1e5 + 10;

bool isPrime(long long x) {
	if (x <= 1)return false;
	if (x == 2)return true;
	if (x % 2 == 0)return false;
	long long m = sqrt(x);
	for (long long i = 3; i <= m; i += 2) {
		if (x % i == 0)return false;
	}
	return true;
}

long long gcd(long long m, long long n) {
	return m % n == 0 ? n : gcd(n, m % n);
}



long long fib[90];

void initFib() {
	fib[0] = fib[1] = 1;

	int i;
	for (i = 2; i < 90; i++) {
		fib[i] = fib[i - 1] + fib[i - 2];

	}
}

int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;

	while (t--) {
		int n;
		cin >> n;
		vector<int> v(n);
		int mmid[110];
		memset(mmid, 0, sizeof(mmid));
		for (auto& val : v) {
			cin >> val;
			mmid[val]++;
		}
		sort(v.begin(), v.end());
		int i, j;
		int ans = 0;
		for (i = 0; i <= 100; i++) {
			int cur = 0;
			for (j = 1; j <= i / 2; j++) {
				cur += min(mmid[j], mmid[i - j]);
			}
			if (i % 2 == 0)cur += mmid[i / 2] / 2 - mmid[i / 2];
			ans = max(ans, cur);
		}
		cout << ans << endl;
	}
	return 0;
}

1399 D. Binary String To Subsequences

题意:有一个01组成的字符串,要把这个字符串分成若干个子序列,使得每个子序列中没有连续的0或者1。要使的子序列数量最少,并输出每个字符在哪个序列中。
思路:用两个队列保存0和1的下标。当遇到1时,如果0的队列为空,则序列数+1。否则取出队首的一个元素。遇到0的时候正好相反。

#include
using namespace std;
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
const long long INF = 1e15;
const int maxn = 1e5 + 10;
 
bool isPrime(long long x) {
	if (x <= 1)return false;
	if (x == 2)return true;
	if (x % 2 == 0)return false;
	long long m = sqrt(x);
	for (long long i = 3; i <= m; i += 2) {
		if (x % i == 0)return false;
	}
	return true;
}
 
long long gcd(long long m, long long n) {
	return m % n == 0 ? n : gcd(n, m % n);
}
 
long long fib[90];
 
void initFib() {
	fib[0] = fib[1] = 1;
 
	int i;
	for (i = 2; i < 90; i++) {
		fib[i] = fib[i - 1] + fib[i - 2];
	
	}
}
 
int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
 
	while (t--) {
		int n;
		cin >> n;
		string str;
		cin >> str;
		vector<int> v(n);
		int cnt = 0;
		int i;
		int flag = 0;
		v[0] = 1;
		deque<int> one,zero;
		int ans = 0;
		for (i = 0; i < n; i++) {
			int tmp;
			if (str[i] == '1') {
				if (zero.size()) {
					tmp = zero.front();
					zero.pop_front();
					one.push_back(tmp);
				}
				else {
					cnt++;
					one.push_back(cnt);
					tmp = cnt;
				}
			}
			else {
				if (one.size()) {
					tmp = one.front();
					one.pop_front();
					zero.push_back(tmp);
				}
				else {
					cnt++;
					zero.push_back(cnt);
					tmp = cnt;
				}
			}
			v[i] = tmp;
		}
		cout << cnt << endl;
		for (i = 0; i < n; i++) {
			if (i)cout << ' ';
			cout << v[i];
		}
		cout << endl;
	}
	return 0;
}

1399 E1. Weights Division (easy version)

题意:有一个n 个顶点的数,顶点为1。每个边都有一个权值。从顶点到叶子节点经过的边的权值和为w。可以进行可以操作 每次将一条边的权值减半(向下取整)。问要使的w<=S。最少要经过几次上诉操作。

思路:w其实就算每个边的权值乘上每个边经过的次数求和求和。所以我们可以先记录一下每条边经过的次数,用堆来维护当前 (权值-权值/2)*经过的次数 最大的边,然后每次修改权重最大的边。

#include
using namespace std;
#define mp(a,b) make_pair(a,b)
typedef pair<long long, int> pli;
typedef pair<int, int> pii;
typedef pair<int, double> pid;
typedef pair<int, long long> pil;
 
const long long INF = 1e15;
const int maxn = 2e5 + 10;
 
bool isPrime(long long x) {
	if (x <= 1)return false;
	if (x == 2)return true;
	if (x % 2 == 0)return false;
	long long m = sqrt(x);
	for (long long i = 3; i <= m; i += 2) {
		if (x % i == 0)return false;
	}
	return true;
}
 
long long gcd(long long m, long long n) {
	return m % n == 0 ? n : gcd(n, m % n);
}
 
 
 
long long fib[90];
 
void initFib() {
	fib[0] = fib[1] = 1;
 
	int i;
	for (i = 2; i < 90; i++) {
		fib[i] = fib[i - 1] + fib[i - 2];
	
	}
}
 
struct cmp {
	bool operator()(const pli& p1, const pli& p2) {
		return (p1.first - p1.first / 2) * p1.second < (p2.first - p2.first / 2)* p2.second;
	}
};
long long sum = 0;
vector<pil> G[maxn];
priority_queue<pli, vector<pli>, cmp> que;
 
int dfs(int cur, int fa) {
	if (G[cur].size() == 1 && cur != 1) return 1;
	int cnt = 0;
	for (auto& [a, b] : G[cur]) {
		if (a == fa)continue;
		int tmp = dfs(a, cur);
		cnt += tmp;
		que.push(mp(b, tmp));
		sum += b * tmp;
	}
	return cnt;
	
}
 
int main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
 
	while (t--) {
		int i;
		long long s;
		sum = 0;
		int n;
		cin >> n >> s;
		for (i = 0; i <= n; i++) {
			G[i].clear();
		}
		int a, b, w;
		for (i = 0; i < n - 1; i++) {
			cin >> a >> b >> w;
			G[a].push_back(mp(b, w));
			G[b].push_back(mp(a, w));
		}
		que = {};
		dfs(1, 0);
		
		int ans = 0;
		while (sum > s) {
			ans++;
			auto [a, b] = que.top();
			que.pop();
			sum -= a * b;
			a /= 2;
			sum += a * b;
			que.push(mp(a, b));
		}
		cout << ans << endl;
	}
	return 0;
}

你可能感兴趣的:(codeforces,ACM)