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;
}
相关推荐
微尘hjx8 小时前
【ByteTrack 04】多轨迹算法ByteTrack改进点
算法·yolo·目标检测·目标跟踪·bytetrack·ultralytics·车跟踪
小向是个Der8 小时前
嵌入式进阶——MCU上电后的动作
c语言·单片机·mcu·学习·链接脚本
bkspiderx11 小时前
基于Socket的广播通信及C语言实现详解
c语言·开发语言·socket·广播·socket的广播通信
小蒋观天下12 小时前
雷击与浪涌防护:前端SPD选型、接地网误区,接地不当反而引入干扰
深度学习·算法·机器学习
WBluuue13 小时前
数据结构与算法:分块(一):块状数组、块状链表
数据结构·c++·算法·链表
澳鹏Appen15 小时前
澳鹏重磅发布ExamOCRBench:面向端到端试卷判分的多任务基准
算法·benchmark·基准评测
benjormin15 小时前
Java数据结构 二叉搜索树
数据结构·算法
人工智能培训15 小时前
知识图谱:结构化表达实体与关系的知识组织技术
大数据·人工智能·算法·重构·生活·知识图谱
地平线开发者15 小时前
QAT 实战:从 PyTorch 模型到 J6E 实板精度与延时验证
pytorch·算法·自动驾驶