Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020

Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final)

A. Kids Seating

题意

给你一个数n,让你输出n个数,在1~4n范围内,且他们之间任意两个数都不能直接相除,且gcd不等于1

思路

因为要使他们gcd不等于1而且任意两个数都不能直接相除,那么要满足这么多数必然是个偶数,在偶数的前提下要使两个数不能直接相除,则倒序输出

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
void solve() {
    int n; cin >> n;
    for (int i = 4 * n, j = 1; j <= n; i -= 2, ++j) {
        cout << i << " ";
    }
    cout <<endl;
}
signed main() {
	int T = 1;
	 cin >> T;
	while (T--) {
		solve();
	}
}

B. Saving the City

给你一个字符串其中1代表地雷0代表啥也没有,然后a是激活一个地雷的代价,b是安放一个地雷的代价,引爆一个地雷时会同时引爆左右两侧的地雷,问你怎么弄才能让所有地雷都爆炸且代价最小。

思路

在一段不连续的空间时我们需要考虑是添加几个地雷还是直接引爆后面的地雷。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define int long long
void solve() {
    int a, b; cin >> a >> b;
    string str; cin >> str;
    vector<int>v1;
    int f = 0;
    for (int i = 0; i < str.size(); ++i) {
        if (str[i] == '1'){
            v1.push_back(i + 1);f = 1;
        }
    }
    int ans = 0;
    for (int i = 1; i < v1.size(); ++i) {
        if (v1[i] - v1[i - 1] > 1) {
            ans = ans + min((v1[i] - v1[i - 1] - 1) * b, a);
        }
    }
    if (ans == 0 && !f) cout << 0 << endl;
    else cout << ans + a << endl;
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int T = 1;
	 cin >> T;
	while (T--) {
		solve();
	}
}

C. The Delivery Dilemma

题意

给你n个食物,食物自己送到你手上需要(a_i)的时间,你去取食物需要(b_i)的时间,问你怎么在最短的时间内取到所有的事物

思路

显然在时间的区间是是有可以和否的两种答案,那么我们二分这个时间。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define int long long
int n;
int a[N], b[N];
bool check(int x) {
    int res = 0;
    for (int i = 1; i <= n; ++i) {
        if (x >= a[i]) continue;
        res += b[i];
    }
    return res <= x;
}
void solve() {
    cin >> n;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    for (int i = 1; i <= n; ++i) cin >> b[i];
    int l = 1, r = 2e14, mid;
    while (l <= r) {
        mid = l + r >> 1;
        if (check(mid)) r = mid - 1;
        else l = mid + 1;
    }
    cout << l << endl;
}
signed main() {
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
}

我们选择一个物品被送来,那么时间小于这个物品都会被送来,大于他的我们只能自己去取,然后找到最小值。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define int long long
pair<LL, LL>a[N];
LL suf[N];
void solve() {
	int n; cin >> n;
	a[0] = {0, 0};
	for (int i = 1; i <= n; ++i) cin >> a[i].first;
	for (int i = 1; i <= n; ++i) cin >> a[i].second;
	sort(a + 1, a + 1 + n);
	suf[n + 1] = 0;
	for (int i = n; i >= 1; --i)suf[i] = suf[i + 1] + a[i].second;
	LL ans = 1e18;
	for (int i = 0; i <= n; ++i) {
		ans = min(ans, max(a[i].first, suf[i + 1]));
	}
	cout << ans << endl;
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int T = 1;
	 cin >> T;
	while (T--) {
		solve();
	}
}

D. Extreme Subtraction

题意

给你n个数,每次可以给前缀或者后缀整体-1,问你能否把整个数组全变为0

思路

我们可以发现这是类似于差分的一个操作,所以我们先将数组变为差分数组。

然后我们考虑给前缀-1,a[1] - 1, a[r + 1] + 1

考虑后缀-1, a[l] - 1 ,a[n + 1] + 1

我们发现有效的操作是除了a[n + 1] + 1以外的操作。

然后剩余的三种操作要保证a[1] - 1的次数要大于等于a[r + 1] + 1的次数。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e4 + 10;
#define int long long
int a[N], d[N];
void solve() {
	int n; cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> a[i]; d[i] = a[i] - a[i - 1];
	}
	int sum = 0;
	for (int i = 1; i <= n; ++i) {
		if (d[i] < 0) sum += -1 * d[i];
	}
	if (a[1] >= sum) cout << "YES
";
	else cout << "NO
";
}
signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int T = 1;
	 cin >> T;
	while (T--) {
		solve();
	}
}
原文地址:https://www.cnblogs.com/waryan/p/14341164.html