Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final)
CF681B
题目链接
题目大意
现在有n个建筑平行排列,用一个长度为n的01字符串代表这个n个建筑,如果字符串某个位置为1,代表这个建筑下面地雷,为0则代表没有,现在设定一种规则,我们可以花 \(a\) 个硬币引爆一个地雷,这个地雷的位置为 \(x\) ,如果 \(x - 1\) 或者 \(x + 1\) 位置处存在地雷,那么这个地雷也将被引爆。我们也可以在没有地雷的建筑下埋地雷,这需要花费 \(b\) 个硬币,然后我们在尝试引爆,现在我们需要引爆所有的地雷来确保城市的安全,问最少需要多少硬币就可以引爆所有地雷。
题解
本题的想法比较直接,考虑两个1的连续区间 \([l_1, r_1]\),\([l_2, r_2]\),如果在这两个区间中间的那个区间填1的代价小于分别引爆这两个区间,那么就采取前者的方案,否则,采取后面的那个方案,具体到实现中就是 \(2 * a \leq a + b * d\),也就是 \(a \leq b * d\) 的时候,我们采取前者方案,否则后者。那我们遍历这个字符串,由于我们不管是填补引爆还是分别引爆,都会将所有的地雷引爆掉,所以这个也就相当于这个字符串 \([l_1, r_2]\) 都是1,所以考虑两个相邻连续1序列必然是最优的,所以我们继续考虑下一个1的连续区间 \([l_3, r_3]\) 也是如此,因此,我们遍历整个字符串即可。
AC代码
#include <bits/stdc++.h>
using namespace std;
#define DBG(x) \
(void)(cout << "L" << __LINE__ \
<< ": " << #x << " = " \
<< (x) << '\n')
#define Lower_bound(v, x) distance(v.begin(), lower_bound(v.begin(), v.end(), x))
#define Upper_bound(v, x) distance(v.begin(), upper_bound(v.begin(), v.end(), x))
typedef long long ll;
const long double PI = (acos(-1));
const long double EPS = 0.0000000001;
const int INF = 0x3f3f3f3f;
const int maxn = 1100000;
void run_case()
{
int T;
cin >> T;
while (T--)
{
int a, b;
cin >> a >> b;
string s;
cin >> s;
int ans = 0;
int d = 1e6;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == '1')
{
ans += min(a, b * d);
d = 0;
}
else d++;
}
cout << ans << "\n";
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setiosflags(ios::fixed) << setprecision(12);
run_case();
cout.flush();
return 0;
}
CF681C
题目链接
题目大意
Petya准备他的生日,准备订 $ n $ 盘菜,有两种方案,一种是让快递员给他送来,一种是自己去取,快递员给他送来,快递员送来是一个并行的过程,每个菜消耗 \(b_i\) 时间,自己取是一个连续的过程,每个菜消耗 \(a_i\) 时间,问最少需要多少时间。
题解
本题的切入点在于快递员送来是一个并行的过程,所以我们用一个结构体维护 \(a\) ,\(b\) 数组,对结构体按 $ a $ 数组元素从小到大进行排序,然后遍历 $ a $ 数组,此时遍历到的第 $ i $ 个元素就是前 $ i $ 盘菜所需要花的时间。同时,我们维护 $ b $ 数组的前缀和和 $ b $ 数组中元素总和,更新 $ ans $ 为 max{sum - pre, a[i].first}即可。
AC代码
#include <bits/stdc++.h>
using namespace std;
#define DBG(x) \
(void)(cout << "L" << __LINE__ \
<< ": " << #x << " = " \
<< (x) << '\n')
#define Lower_bound(v, x) distance(v.begin(), lower_bound(v.begin(), v.end(), x))
#define Upper_bound(v, x) distance(v.begin(), upper_bound(v.begin(), v.end(), x))
typedef long long ll;
const long double PI = (acos(-1));
const long double EPS = 0.0000000001;
const int INF = 0x3f3f3f3f;
const int maxn = 1100000;
pair<int, int> a[maxn];
void run_case()
{
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].first;
}
ll sum = 0;
for (int i = 1; i <= n; i++)
{
cin >> a[i].second;
sum += 1ll * a[i].second;
}
sort(a + 1, a + 1 + n);
ll ans = sum;
ll pre = 0;
for (int i = 1; i <= n; i++)
{
pre += 1ll * a[i].second;
ans = min(ans, max(sum - pre, 1ll * a[i].first));
}
cout << ans << "\n";
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setiosflags(ios::fixed) << setprecision(12);
run_case();
cout.flush();
return 0;
}
CF681D
题目链接
题目大意
给你一个数组\(a\),每次操作可以将数组的前\(k\)个元素或者后\(k\)个元素减1,问经过有限次的操作能不能把这个数组全部变成0。
题解
前缀区间和后缀区间减\(1\),我们可以自然想到使用差分的方法来解决这个问题,设一个数组\(a\),它的差分数组为\(df\),对\(a\)数组中区间\([l,r]\)中所有的元素减\(1\),相当于对差分数组\(df[l]-1\)和\(df[r+1]+1\),所以在这个问题中,我们只需要保证\(df[1] = 0\),然后\(df\)数组其余所有元素为0即可。在对前缀区间操作时,差分数组\(df[1]\)减小,数组中其余元素增加,进行后缀区间操作时,因为我们这时候是对\(d[n+1]\)进行加1,所以对这个问题没有影响,我们可以任意把差分数组中大于\(0\)的元素减到\(0\),因此,我们只需要判断\(d[1]\)是否大于等于差分数组中负数之和的绝对值即可。
#include <bits/stdc++.h>
using namespace std;
#define DBG(x) \
(void)(cout << "L" << __LINE__ \
<< ": " << #x << " = " \
<< (x) << '\n')
#define Lower_bound(v, x) distance(v.begin(), lower_bound(v.begin(), v.end(), x))
#define Upper_bound(v, x) distance(v.begin(), upper_bound(v.begin(), v.end(), x))
typedef long long ll;
const long double PI = (acos(-1));
const long double EPS = 0.0000000001;
const int INF = 0x3f3f3f3f;
const int maxn = 110000;
int a[maxn];
int df[maxn];
void run_case()
{
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++)
{
df[i] = a[i] - a[i - 1];
}
int cnt = 0;
for (int i = 1; i <= n; i++)
{
if (df[i] < 0) cnt += df[i];
}
cnt = -cnt;
if (cnt > df[1]) cout << "NO\n";
else cout << "YES\n";
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setiosflags(ios::fixed) << setprecision(12);
run_case();
cout.flush();
return 0;
}

浙公网安备 33010602011771号