Educational Codeforces Round 131 ( Div. 2) A - D

A. Grass Field

思路:

只有4种情况,枚举一下即可

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int t;
int main () {
	cin >> t;
	while (t--) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		if (!a && !b && !c && !d) cout << "0" << endl;
		else if (a && b && c && d) cout << "2" << endl;
		else cout << "1" << endl; 
	}
	return 0;
}

B. Permutation

题意:

给定n,找出使得满足a[i] * d = a[i + 1]的a[i]最多的d和此时的全排列

思路:

显然有d = 2,然后从1开始枚举倍数就可以了

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
int t, mp[200005];
int main () {
	cin >> t;
	while (t--) {
		int n;
		cin >> n;
		memset(mp, 0, sizeof mp);
		cout << "2" << endl;
		for (int i = 1; i <= n; i++) {
			if (!mp[i]) {
				for (int j = 0; pow(2, j) * i <= n; j++) {
					cout << pow(2, j) * i << endl;
					mp[(int)pow(2, j) * i] = 1;
				}
			}
		}
		cout << endl;
		
	}
	return 0;
}

C. Schedule Management

题意:

有n个工人,m分工作,每个工作都有一个工人对此比较熟练,需要1h,其他不熟练的工人做这分工作需要2h
求做完工作的最短时间

思路:

二分答案,在mid时间内,枚举每个工人,计算工人对于总任务的贡献量。用b[i]记录每个工人熟练的工作数,在mid时间内优先做熟练的工作,如果b[i] > mid,贡献量为mid, 否则贡献量为b[i] + (mid - b[i]) / 2
累计贡献check即可。

代码


#include <bits/stdc++.h>
#define ll long long
using namespace std;
int t;
ll n, m, a[200005], b[200005];
void bs (ll l ,ll r) {
	ll ans;
	while (l <= r) {
		ll mid = (l + r) >> 1, res = 0;
		for (int i = 1; i <= n; i++) {
			if (b[i] < mid ) res += b[i] + (mid - b[i]) / 2 ;
			else res += mid;
		}
		if (res < m) l = mid + 1;
		else r = mid - 1, ans = mid;
	}
	cout << ans << endl;
}
int main () {
	cin >> t;
	while (t--) {
		memset(b, 0, sizeof b);
		cin >> n >> m;
		for (int i = 1; i <= m; i++) cin >> a[i],b[a[i]] ++;
		bs(1, 2 * m);
		
	}
	return 0;
}

D. Permutation Restoration(补)

题意:

有一个1-n的全排列a[n],存在b[n]使得 \(b_i = [\frac{i}{a_i}]\), 给定n和b[n]求a[n]

思路:

对于i,存在\(b_i \leq\ \frac{i}{a_i} < b_{i} + 1\)
反解出\(\frac{i}{b_i+1} < a_i \leq\ \frac{i}{b_i} ,\frac{i}{b_i+1}+1\leq\ a_i \leq\ \frac{i}{b_i}\)
预处理出每一个位置i的左右区间[l, r], 当\(b_i = 0\) 时,r = n
遍历i从1-n,对于每一个i,寻找出满足 \(l\leq\ i \leq\ r\) 的位置,贪心选择r最小的位置放i
用一个堆来取出r最小的位置

代码:

#include <bits/stdc++.h>
using namespace std;
#define MAXN 500007
typedef pair<int, int> PII;
vector<PII> g[MAXN];
priority_queue<PII, vector<PII>, greater<PII> >q;
int n,a[MAXN],b[MAXN];
void solve() {
    cin >> n;
    for (int i = 1; i <= n; i++) g[i].clear();
    for (int i = 1; i <= n; i++) cin >> b[i];
    for (int i = 1; i <= n; i++) {
        int L = i / (b[i] + 1) + 1;
        int R = b[i] == 0 ? n : i / b[i];
        g[L].push_back({ R,i });
    }
    for (int i = 1; i <= n; i++) {
        for (auto p : g[i]) q.push(p);
        PII p = q.top(); q.pop();
        a[p.second] = i;
    }
    for (int i = 1; i <= n; i++)cout << a[i] << " ";
    cout << endl;
}
int main () {
	int t;
	cin >> t;
	while (t--) solve();
	return 0;
}
posted @ 2022-07-09 10:03  misasteria  阅读(114)  评论(2编辑  收藏  举报