[每日随题2] 模拟 - 贪心 - 贪心
整体概述
- 难度:1400 -> 1800 -> 2200
2028B.Alice's Adventures in Permuting
-
标签:模拟
-
前置知识:无
-
难度:Div.2.B 1400
题目描述:

输入格式:

输出格式:

样例输入:
7
10 1 0
1 2 3
100 2 1
3 0 1
3 0 0
1000000000000000000 0 0
1000000000000000000 1000000000000000000 1000000000000000000
样例输出:
0
1
50
2
-1
-1
1000000000000000000
解题思路:
-
注意到当 \(b\ne0\) 时,我们只需要知道在 \([0,n-1]\) 中出现了多少个数字,假设为 \(m\) 个数字,其余的数字都需要一步步地操作获得,所以答案就为 \(n-m\)。
-
当 \(b=0\) 时。若 \(c\ge n\) 则答案为 \(n\);若 \(c=n-1\) 或 \(c=n-2\) 则答案为 \(n-1\);否则无法最后形成一个排列(手动模拟一下 \(c\) 更小的情况),输出 \(-1\)。
完整代码
#include<iostream>
#define Size(x) ((int)(x).size())
#define int long long
using namespace std;
const int N = 5e5+5;
inline void solve(){
int n,b,c; cin >> n >> b >> c;
if(b == 0){
if(c >= n) cout << n << '\n';
else if(c <= n-3) cout << -1 << '\n';
else cout << n-1 << '\n';
}else cout << (c>=n ? n : n-((n-1-c)/b+1)) << '\n';
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; cin >> T;
while(T--) solve();
return 0;
}
1990D.Grid Puzzle
-
标签:贪心
-
前置知识:无
-
难度:Div.2.D 1800
题目描述:

输入格式:

输出格式:

样例输入:
10
1
0
4
2 4 4 2
4
3 2 1 0
3
0 3 0
3
0 1 3
3
3 1 0
4
3 1 0 3
4
0 2 2 2
6
1 3 4 2 0 4
8
2 2 5 2 3 4 2 4
样例输出:
0
3
2
1
2
2
3
2
4
6
解题思路:
-
由于 n 很大,我们考虑每行之间的相互影响。
-
我们不难发现,如果第 \(i\) 行的 \(a_i\) 很大,那必定会使用操作 \(2\)。手动画几个图可以发现,当 \(a_i \ge 5\) 时,这一行直接选择方案 \(2\) 即是最优(可以分类讨论证明)。
-
那么我们按行来考虑,只有当第 \(i\) 行的 \(a_i\) 小于等于 \(4\) 的时候才会受到上一行的影响,那么我们只需要关注前面 \(4\) 个格子的颜色情况。
-
我们可以记上一行的状态 \(last\) 有 \(4\) 种,分别为
0:该行无黑格;1:前两格有黑格;2:后两格有黑格;3:前两格和后两格都有黑格。\(last = 1\) 时,只填一个 \(2*2\) 在前两格
\(last = 2\) 时,只填一个 \(2*2\) 在后两格
\(last = 3\) 时,若 \(a_i\le2\) 则上一行用操作 \(2\),否则填两个 \(2*2\)。 -
从头到尾模拟一遍,最后注意一下最后一行的状态,\(last\ne 0\) 则再用一次操作 \(2\) 给最后一行即可。
完整代码
#include<bits/stdc++.h>
#define Size(x) ((int)(x).size())
#define int long long
using namespace std;
const int N = 2e5+5;
int a[N];
inline void solve(){
int n; cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
int last = 0, res = 0; // last 表示上一行状态, 0:无 1:前两个有 2:后两个 3:全有
for(int i=1;i<=n;i++){
if(a[i] >= 5 || a[i] == 0){
res += (a[i] > 0) + (last > 0);
last = 0;
}else{
if(last == 0){
last = (a[i] <= 2 ? 1 : 3);
}else if(last == 1){
res += 1;
last = a[i] <= 2 ? 0 : 2;
}else if(last == 2){
res += 1;
last = 1;
}else{
if(a[i] <= 2) res += 1, last = 1;
else res += 2, last = 0;
}
}
}
res += (last > 0);
cout << res << '\n';
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; cin >> T;
while(T--) solve();
return 0;
}
1415E.New Game Plus!
-
标签:贪心
-
前置知识:STL-priority_queue
-
难度:Technocup2021.ROUND2.E 2200
题目描述:

输入格式:

输出格式:

样例输入:
3 0
1 1 1
5 1
-1 -2 -3 -4 5
13 2
3 1 4 1 5 -9 -2 -6 -5 -3 -5 -8 -9
样例输出:
3
11
71
解题思路:
-
注意到每次使用漏洞后,相当于重新启动了一局游戏。共 \(k+1\) 局游戏之间相互独立,那么我们考虑将 \(n\) 个 \(BOSS\) 划分到 \(k+1\) 局游戏之中。
-
我们不难发现,每局游戏中某个奖励为 \(a_i\) 的 \(BOSS\) 被打败后,若本剧游戏后续还有 \(x\) 个 \(BOSS\) 会被打败,则该 \(BOSS\) 带来的贡献为 \(x\times a_i\),所以 \(a_i\) 越大的 \(BOSS\) 需要越先打败。
-
所以我们将 \(n\) 个 \(BOSS\) 按 \(a_i\) 从大到小排序,依次考虑每一个 \(BOSS\) 要被放入哪一局游戏。打败一个新的 \(BOSS\) 相当于选择一局游戏,获得其现有的分数。那么我们每次选择现有分数最大的那局游戏,打败该 \(BOSS\) 获取当前奖励,随后更新新的 \(BOSS\) 奖励。
-
依次处理完所有 \(BOSS\) 即可,总复杂度 \(O(nlog_2^n)\)。
完整代码
#include<bits/stdc++.h>
#define Size(x) ((int)(x).size())
#define int long long
using namespace std;
const int N = 5e5+5;
int a[N],n,k;
priority_queue<int,vector<int>,less<int>> qu;
inline void solve(){
cin >> n >> k;
for(int i=1;i<=n;i++) cin >> a[i];
sort(a+1,a+1+n,[&](int x,int y){return x > y;});
for(int i=1;i<=k+1;i++) qu.push(0);
int res = 0;
for(int i=1;i<=n;i++){
int x = qu.top(); qu.pop();
res += x;
qu.push(x+a[i]);
}
cout << res;
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int T; T = 1;
while(T--) solve();
return 0;
}

每日练题中,难度简单,一起保持手感~
浙公网安备 33010602011771号