A. Kids Seating
满足所有数 gcd不为1,且无法相互整除
选择数的范围是
1
1
1 ~
4
n
4n
4n,从
4
n
4n
4n 开始倒着输出
n
n
n个偶数即可
B. Saving the City
题意:1代表雷,0代表空,花费a可以引爆连着的雷,也可以花费b埋下一颗地雷,求引爆所有的雷的最小花费
对于全是0和只有一段1的情况特判即可
1的段数大于1,那么对于两段1来说, 要么用 a*2 引爆,要么把中间的 0 填上雷消耗 a + b
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 9;
int n, m;
char s[maxn];
void work()
{
int a, b;
cin >> a >> b;
cin >> (s + 1);
s[0] = '1';
vector <int> v;
n = strlen(s + 1);
while(s[n] == '0' && n >= 1) --n;
int i = 1;
while(s[i] == '0' && i <= n) ++i;
if(n < 1)// 全是 0
{
cout << 0 << endl;return;
}
for(; i <= n; ++i)
if(s[i] == '0')
{
int j = i;
while(s[j] == '0' && j <= n) ++j;
if(j == 2);
else v.push_back(j - i);
i = j - 1;
}
sort(v.begin(), v.end());
int ans = v.size();
if(ans) ++ans;// ans + 1 段 1
else// 一段1
{
cout << a << endl;return;
}
ans *= a;// 不埋地雷的花费
for(int i = 0; i < v.size(); ++i)
{
if(a > b * v[i])
{
ans -= a;
ans += b * v[i];
}
}
cout << ans << endl;
}
int main()
{
int TT;cin>>TT;while(TT--)
work();
return 0;
}
C. The Delivery Dilemma
贪心
将外卖时间长的加入 sum,维护 i + 1 之后的外卖时间最大值
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5 + 9;
int n;
ll f[maxn];
struct node
{
ll a, b;
}c[maxn];
bool cmp(node a, node b)
{
if(a.a != b.a) return a.a > b.a;
else return a.b < b.b;
}
void work()
{
ll ans = 0, sum = 0;
cin >> n;
for(int i = 1; i <= n; ++i) scanf("%lld", &c[i].a), ans = max(ans, c[i].a);
for(int i = 1; i <= n; ++i) scanf("%lld", &c[i].b);
sort(c+1,c+1+n,cmp);
f[n+1] = 0;
for(int i = n; i >= 1; --i)
f[i] = max(c[i].a, f[i+1]);
for(int i = 1; i <= n; ++i)
ans = min(ans, max(sum+c[i].b, f[i+1])), sum += c[i].b;
cout << ans << endl;
}
int main()
{
int TT;cin>>TT;while(TT--)
work();
return 0;
}
D. Extreme Subtraction
题意:给你
n
n
n个数,每次操作给前缀或者后缀
−
1
-1
−1,问能不能把数组变成全
0
0
0
思路:
我们可以发现这是类似于差分的一个操作,所以我们先将数组变为差分数组。
然后考虑前缀
−
1
-1
−1,
a
[
1
]
−
1
a[1]-1
a[1]−1,
a
[
r
+
1
]
+
1
a[r+1]+1
a[r+1]+1
后缀
−
1
-1
−1,
a
[
l
]
−
1
a[l]-1
a[l]−1,
a
[
n
+
1
]
+
1
a[n+1]+1
a[n+1]+1
我们发现有效的操作是除了
a
[
n
+
1
]
+
1
a[n+1]+1
a[n+1]+1以外的操作
要使得数组全为0,只需要让差分数组变成0即可
对于差分数组中
2
2
2 到
n
n
n 大于
0
0
0 的数,使用后缀
−
1
-1
−1的操作可以全部变成0
而对于小于
0
0
0 的数,
2
<
=
r
+
1
<
=
n
2<=r+1<=n
2<=r+1<=n,使用前缀
−
1
-1
−1 的操作,要保证
a
[
1
]
−
1
a[1]-1
a[1]−1的次数要大于等于
a
[
r
+
1
]
+
1
a[r+1]+1
a[r+1]+1的次数。
这样差分只有
a
[
1
]
a[1]
a[1]不一定为0,求前缀和后发现原数组变成了所有相等的数,可以消除
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 3e4 + 9;
const int inf = 0x3f3f3f3f;
int n;
int a[maxn];
void work()
{
cin >> n;
for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
for(int i = n; i >= 1; --i)
a[i] -= a[i-1];// 构建差分数组
int ans = 0;
for(int i = 2; i <= n; ++i) if(a[i] < 0)
ans -= a[i];// 统计 a[r + 1] + 1 的数量
if(a[1] >= ans) cout << "YES\n";
else cout << "NO\n";
}
int main()
{
int TT;cin>>TT;while(TT--)
work();
return 0;
}