Atcoder beginner 278 (A ~ E)解题报告
2022.11.19
文章目录
- Atcoder beginner 278 (A ~ E)解题报告
- [A - Shift](https://atcoder.jp/contests/abc278/tasks/abc278_a)
- [B - Misjudge the Time](https://atcoder.jp/contests/abc278/tasks/abc278_b)
- [C - FF](https://atcoder.jp/contests/abc278/tasks/abc278_c)
- [D - All Assign Point Add](https://atcoder.jp/contests/abc278/tasks/abc278_d)
- [E - Grid Filling](https://atcoder.jp/contests/abc278/tasks/abc278_e)
A - Shift
题目大意
给定一个数 N 和 K 将长度为 N 数组的前 K 项删除后输出后面内容,后面补零
样例
输入
3 2
2 7 8
输出
8 0 0
思路
直接输出后N - K 项不足补零,若K 大于 N 直接输出 0 即可
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 110;
int n , k;
int a[MAXN];
int main(){
cin >> n >> k;
for(int i = 1; i <= n; ++i)
cin >> a[i];
if(k > n){
for(int i = 1; i < n; ++i)
cout << 0 << " ";
cout << 0 << endl;
return 0;
}
for(int i = k + 1; i <= n; ++i)
cout << a[i] << " ";
for(int i = 1; i < k; ++i)
cout << 0 << " ";
cout << 0 << endl;
return 0;
}
B - Misjudge the Time
题目大意
给定H M , A , B :C , D将B和C调换按24小时计时法仍然合法的包括现在的第一个时间
样例
输入 1 23
输出 1 23
思路
直接加上时间模拟即可
代码
#include <bits/stdc++.h>
using namespace std;
int h , m;
int main(){
cin >> h >> m;
int a , b , c , d;
a = h / 10 , b = h % 10 , c = m / 10 , d = m % 10;
while(a * 10 + c > 23 || b * 10 + d > 59){
d++;
if(d >= 10)
d %= 10 , c++;
if(c >= 6)
c %= 6 , b++;
if(b >= 10)
b %= 10 , a++;
if(a == 2 && b >= 4)
b %= 4 , a = 0;
}
cout << a * 10 + b << " " << c * 10 + d << endl;
return 0;
}
C - FF
题目大意
输入三种操作
T = 1 时 A 关注 B
T = 2 时 B 关注 A(若已关注则无影响)
T = 3 时查询A,B是否互相关注,是输出Yes,否则输出No
样例
输入3 9
1 1 2
3 1 2
1 2 1
3 1 2
1 2 3
1 3 2
3 1 3
2 1 2
3 1 2
输出
No
Yes
No
No
思路
考虑比较笨拙的方法,用较慢的字符串和map映射直接存储两人之间的关系
代码
#include <bits/stdc++.h>
using namespace std;
int n , Q , t;
map<string , int> mp;
string st , a , b , stt;
int main(){
st = "" , stt = "";
cin >> n >> Q;
while(Q--){
cin >> t >> a >> b;
st = a + " " + b;
stt = b + " " + a;
if(t == 1)
mp[st] = 1;
else if(t == 2)
mp[st] = 0;
else{
if(mp[st] && mp[stt])
cout << "Yes" << endl;
else3
cout << "No" << endl;
}
}
return 0;
}
D - All Assign Point Add
题目大意
给定3种操作
1 A x 将A数组的每个值都变成x
2 i x 将序号为i的值加上x
3 i 查询序号为i的值
样例
输入
5
3 1 4 1 5
6
3 2
2 3 4
3 3
1 1
2 3 4
3 3
输出
1
8
5
思路1
进行一种懒处理,哈希表判断
如果遇到的是操作1那么将需要改变的值赋值到变量K上
如果在操作1之后遇到操作2那么直接改变序号为i的数的值并将哈希表位置改为true
如果是操作3查询 若哈希为false则输出K否则输出a[i]
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 10;
int n , q;
bool vh[MAXN];
long long a[MAXN] , f[MAXN];
int t , x , y;
int main(){
cin >> n;
for(int i = 1; i <= n; ++i){
cin >> a[i];
vh[i] = false;
}
cin >> q;
int k = 0 , fe = 0 , p = 0;
while(q--){
cin >> t;
if(t == 1){
cin >> x;
if(fe == 0)
k = x;
else{
k = x;
for(int i = 1; i <= p; ++i)
vh[f[i]] = false;
p = 0;
}
fe++;
}
else if(t == 2){
cin >> x >> y;
if(fe == 0)
a[x] += y;
else{
if(!vh[x])
a[x] = k + y;
else
a[x] += y;
f[++p] = x;
vh[x] = true;
}
}
else{
cin >> x;
if(fe == 0)
cout << a[x] << endl;
else{
if(vh[x])
cout << a[x] << endl;
else
cout << k << endl;
}
}
}
return 0;
}
思路2
考虑直接用map解决,每次清空不会超时
代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int n, q;
ll ass;
map<int, ll> a;
signed main() {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
cin >> q;
for (int i = 1; i <= q; ++i) {
int t, k; cin >> t;
ll x;
if (t == 1) {
cin >> ass;
a.clear();
}
else if (t == 2) {
cin >> k >> x;
a[k] += x;
}
else {
cin >> k;
cout << a[k] + ass << "\n";
}
}
return 0;
}
E - Grid Filling
题目大意
在长为H , 宽为W 的矩阵中覆盖长为h,宽为w的矩阵
输出每种情况中剩下的不同元素个数
思路1
直接O(n^4)方模拟可以过
代码
#include<bits/stdc++.h>
using namespace std;
int a[310][310] , h , w , n , r , c;
vector <int> cnt(310);
int main(){
cin >> h >> w >> n >> r >> c;
for(int i = 0; i < 308; i++)
cnt[i] = 0;
for(int i = 1;i <= h; i++)
for(int j = 1;j <= w; j++)
cin >> a[i][j] , cnt[a[i][j]]++;
for(int i = 1; i <= h - r + 1; i++){
for(int j = 1; j <= w - c + 1; j++){
vector <int> tcnt(cnt);
for(int k = i; k <= i + r - 1; k++)
for(int l = j; l <= j + c - 1; l++)
tcnt[a[k][l]]--;
int ans = 0;
for(int k = 1; k <= n; k++)
if(tcnt[k])
ans++;
cout << ans << " ";
}
cout << endl;
}
return 0;
}
思路2
简单优化到O(n^3)
考虑二维前缀和,定义三维数组 a[k][i][j]分别表示 k 数字在 i 行 j 列中有多少个
然后三层循环查找解,枚举最右下角端点 , 直接拿右下角的最大前缀和,减去维护的矩阵就可以了
代码
#include<bits/stdc++.h>
using namespace std;
int H, W, N, h, w;
int mp[310][310];
int a[310][310][310];
int sum[310][310][310];
int main(){
cin >> H >> W >> N >> h >> w;
for(int i = 1; i <= H; i++){
for(int j = 1; j <= W; j++){
cin >> mp[i][j];
a[i][j][mp[i][j]]++;
}
}
for(int i = 1; i <= H; i++)
for(int j = 1; j <= W; j++)
for(int k = 1; k <= N; k++)
sum[i][j][k] = sum[i][j][k] + a[i][j][k] + sum[i - 1][j][k] + sum[i][j - 1][k] - sum[i - 1][j - 1][k];
int ans = 0;
for(int i = h; i <= H; i++){
for(int j = w; j <= W; j++){
ans = 0;
for(int k = 1; k <= N; k++)
ans += (sum[H][W][k] - (sum[i][j][k] - sum[i][j - w][k] - sum[i - h][j][k] + sum[i - h][j - w][k]) != 0);
cout << ans << " ";
}
cout << endl;
}
}