AT_abc443_C~E题题解

problem C \Large problem\ C problem C

不算太复杂。

每次记录上一次关机的时间 lastlastlast,当青木在 aia_iai 来过时,如果 last+100<ailast+100<a_ilast+100<ai,则答案加上 ai−(last+100)a_i-(last+100)ai−(last+100),否则不做任何处理。

当 n=0n=0n=0 时记得特判。

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long

using namespace std;

int a[300005];
int main(){
	int n,t;
	cin>>n>>t;
	for(int i=1;i<=n;i++)cin>>a[i];
	if(n==0){//一次都没有来过,特判 
		cout<<t;
		return 0;
	}
	int ans=a[1];
	int las=a[1];//记录上次关机时间 
	a[n+1]=t;
	for(int i=2;i<=n+1;i++){
		if(las+100<a[i]){
			ans+=a[i]-las-100;
			las=a[i];
		}
	}
	cout<<ans;
	return 0;
}

problem D \Large problem\ D problem D

赛时没过QWQ。

题意:给一个矩阵,每一列都有一颗棋子,每次可以挑一个棋子向上移动一格,要求所有相邻的棋子行编号差的绝对值不超过 111,求最小操作次数。

每个棋子都对左右两边相邻的棋子有约束,如果一个棋子 iii 可能的高度是 fif_ifi,那么它左边的棋子 i−1i-1i−1 的最低可能的高度就是 min⁡(fi−1,fi+1)\min(f_{i-1},f_i+1)min(fi−1,fi+1),同样的,它右边的棋子 i+1i+1i+1 的最低可能的高度就是 min⁡(fi+1,fi+1)\min(f_{i+1},f_i+1)min(fi+1,fi+1)。

因此我们正着循环一遍,每次令 fi=min⁡(fi,fi−1+1)f_i=\min(f_i,f_{i-1}+1)fi=min(fi,fi−1+1),再倒过来循环,每次使 fi=min⁡(fi,fi+1+1)f_i=\min(f_i,f_{i+1}+1)fi=min(fi,fi+1+1),最后得到的 fff 就是能使答案最小且满足条件的解,它与原数组的差之和就是要操作的次数。

代码:

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long

using namespace std;

ll a[300005];
ll b[300005];
void solve(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		b[i]=a[i];
	}
	ll ans=0;
	for(int i=2;i<=n;i++)b[i]=min(b[i-1]+1,b[i]);
	for(int i=n-1;i>=1;i--)b[i]=min(b[i+1]+1,b[i]);
	for(int i=1;i<=n;i++)ans+=a[i]-b[i];//差之和就是答案
	cout<<ans<<endl;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		solve();
	} 
	return 0;
}

problem E \Large problem\ E problem E

光顾着想 D 了,E都没看。

借鉴了一位大佬的思路,orz。

题意:你站在一个地图的指定点处,每次可以向左上,正上或右上方移动一格,如果这个格子是墙,且这一列这个格子下方没有墙,就可以将这个墙清除,问对于第一行每一个点是否能到达。

观察清除墙的规则,可以发现,如果到达一列最下方的或以下,一直往上走,那么这一列所有的墙都可以被清空,换句话说,第 jjj 列最后一个障碍在第 kkk 行,且当前到达了 (i,j)(i,j)(i,j) 且 i≥ki\ge ki≥k,那么第 jjj 列的所有障碍都可以被无视,相当于第 jjj 列被打通了。

记录每一列的打通情况,广搜可以解决。

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long

using namespace std;

char a[3005][3005];
bool vis[3005][3005];
//记录是否到达过 
int ope[3005],las[3005];
// ope记录打通情况,las表示每一列的最后一个障碍 
int dx[4]={-1,-1,-1};
int dy[4]={-1,0,1};//增量数组减少码量 
void solve(){
	int n,c;
	scanf("%d%d",&n,&c);
	for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
	for(int i=1;i<=n;i++){
		ope[i]=las[i]=0;
		for(int j=1;j<=n;j++)vis[i][j]=0;
	}//多组数据记得清空 
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(a[i][j]=='#')
				las[j]=max(las[j],i);
	queue<pair<int,int> > q;
	q.push({n,c});
	vis[n][c]=1;
	ope[c]=1;
	while(q.size()){
		int x=q.front().first;
		int y=q.front().second;
		q.pop();
		for(int i=0;i<3;i++){
			int xx=x+dx[i],yy=y+dy[i];
			if(xx<1||xx>n||yy<1||yy>n||vis[xx][yy])continue;
			if(a[xx][yy]=='#'&&!ope[yy]&&xx<las[yy])continue;
			if(xx>=las[yy])ope[yy]=1;
			vis[xx][yy]=1;
			q.push({xx,yy});
		} 
	}
	for(int i=1;i<=n;i++)cout<<vis[1][i];
	cout<<endl;
	return;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		solve();
	} 
	return 0;
}
相关推荐
梵刹古音2 小时前
【C语言】 浮点型(实型)变量
c语言·开发语言·嵌入式
u0109272712 小时前
模板元编程调试方法
开发语言·c++·算法
2401_838472512 小时前
C++图形编程(OpenGL)
开发语言·c++·算法
-dzk-2 小时前
【代码随想录】LC 203.移除链表元素
c语言·数据结构·c++·算法·链表
进击的小头3 小时前
陷波器实现(针对性滤除特定频率噪声)
c语言·python·算法
知无不研3 小时前
冒泡排序算法
算法·冒泡排序·排序
毅炼3 小时前
hot100打卡——day17
java·数据结构·算法·leetcode·深度优先
Tisfy3 小时前
LeetCode 3010.将数组分成最小总代价的子数组 I:排序 OR 维护最小次小
算法·leetcode·题解·排序·最小次小值
Learn Beyond Limits3 小时前
文献阅读:A Probabilistic U-Net for Segmentation of Ambiguous Images
论文阅读·人工智能·深度学习·算法·机器学习·计算机视觉·ai