Atcoder beginner 278 (A ~ E)解题报告

Atcoder beginner 278 (A ~ E)解题报告

2022.11.19

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;
    }
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值