acwing 第24场周赛

acwing 第24场周赛

本次的周赛有三道题目:模拟,枚举,模拟

acwing 4070. 异或

链接:4070. 异或 - AcWing题库

题目描述

4070.png

解题思路

很简单的模拟,输入的时候记录最大值和最后一个输入,甚至连数组都不用开

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
int n,maxx,a;
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a);
		maxx=max(maxx,a);
	}
	a^=maxx;//这里的a就是最后一个元素
	printf("%d",a);
	return 0;
}

acwing 4071. 国际象棋

链接:4071. 国际象棋 - AcWing题库

题目描述

4071.png

解题思路

棋盘上有车和马a,问如何放放马b

枚举出所有不能放马的格子,用总格子数减去就行了

不能放马的格子就三种情况:车所在的一整行和一整列和马a自身所在的格子、马a能跳到的格子、马b放下后能吃到车的格子

第一种情况很好处理,二三两种情况也不难想:将马a和车作为起点,马走日为一步,下一步能走到的格子就是不能放的格子

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
int fx[8]={2,1,-1,-2,-2,-1,1,2};
int fy[8]={1,2,2,1,-1,-2,-2,-1};
int ans=16;//车能走到的格子15格加上马1自身的格子
int c1,c2;//c是车的坐标
int m1,m2;//m是马a的坐标
bool vis[10][10];
int main(){
	char a[2],b[2];
	scanf("%s",&a);
	scanf("%s",&b);
	c1=a[0]-'a';
	c2=a[1]-'0'-1;
	m1=b[0]-'a';
	m2=b[1]-'0'-1;
	for(int i=0;i<8;i++) vis[c1][i]=1;//车所在的行和列全部不可放置
	for(int i=0;i<8;i++) vis[i][c2]=1;
	vis[m1][m2]=1;//马自身所在的格子
	for(int i=0;i<8;i++){
        //计算马a能到达的格子
		int tox=m1+fx[i];
		int toy=m2+fy[i];//马走日为一步
		if(tox>=0&&tox<8&&toy>=0&&toy<8&&!vis[tox][toy]) {ans++;vis[tox][toy]=1;}//到达的坐标必须在棋盘上且该点未被计算过
        //计算能吃到车的格子
		tox=c1+fx[i];
		toy=c2+fy[i];
		if(tox>=0&&tox<8&&toy>=0&&toy<8&&!vis[tox][toy]) {ans++;vis[tox][toy]=1;}
	}
	ans=64-ans;//总格子数减去不可放置格子数
	printf("%d",ans);
	return 0;
}

acwing 4072.

链接:4072. 习题册 - AcWing题库

题目描述

4072.png

解题思路

题目中的知识点总数只有3个,每本习题册只有1-2个知识点,每次询问只会包含一个知识点

所以很好想的思路就是用3个vector数组记录包含a,b,c三个知识点的练习册,按价钱从小到大排序,询问一个就输出并pop掉一个

那么问题来了:一本习题册有两个知识点a和b,a数组pop掉了,b怎么办?

那我们就用一个vis数组记录哪本被买了就行了,用struct记录下每本习题册的id和cost,vector数组按cost大小排序,每次输出最小cost的,如果数组空了买不了就输出-1

主要计算是在排序那,所以时间复杂度是O(nlogn)

注意事项

题目中保证了每本习题册价钱不一样,所以没有同价钱买哪一本更优的问题

需要注意的是每本习题册包含的知识点分两次输入且可能相同,记得不要重复push进习题册数组

还有一个优化,vector的pop_back操作比erase快,所以最好按习题册价钱从高到低排序,从数组尾读取,这样代码好写时间也快

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int N=2e5+10;
struct node{
	int id;
	int cost;
};
vector<node> a,b,c;//包含a,b,c三个知识点的习题册数组
int n,m;
int p[N],a1[N],b1;//p是每本习题册的价钱,a1是每本习题册包含的第一个知识点,b1是第二个知识点
bool vis[N];//记录习题册是否被买走
bool cmp(node x,node y){
	if(x.cost>y.cost) return true;//按从大到小排序
	return false;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&p[i]);//cost
	for(int i=1;i<=n;i++){
		scanf("%d",&a1[i]);//读入第一个知识点
		node temp;
		temp.id=i;
		temp.cost=p[i];
        //按包含的知识点分别进数组
		if(a1[i]==1){
			a.push_back(temp);
		}
		else if(a1[i]==2){
			b.push_back(temp);
		}
		else{
			c.push_back(temp);
		}
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&b1);
		if(b1==a1[i]) continue;//如果第二个知识点和第一个一样直接continue
		node temp;
		temp.id=i;
		temp.cost=p[i];
		if(b1==1){
			a.push_back(temp);
		}
		else if(b1==2){
			b.push_back(temp);
		}
		else{
			c.push_back(temp);
		}
	}
	sort(a.begin(),a.end(),cmp);
	sort(b.begin(),b.end(),cmp);
	sort(c.begin(),c.end(),cmp);
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int op;//询问知识点
		scanf("%d",&op);
		bool flag=0;
		if(op==1){
			for(int j=a.size()-1;j>=0;j--){
				node temp=a[j];
				a.pop_back();
				if(!vis[temp.id]){
					printf("%d ",temp.cost);
					vis[temp.id]=1;
					flag=1;
					break;
				}
			}
		}
		else if(op==2){
			for(int j=b.size()-1;j>=0;j--){
				node temp=b[j];
				b.pop_back();
				if(!vis[temp.id]){
					printf("%d ",temp.cost);
					vis[temp.id]=1;
					flag=1;
					break;
				}
			}
		}
		else{
			for(int j=c.size()-1;j>=0;j--){
				node temp=c[j];
				c.pop_back();
				if(!vis[temp.id]){
					printf("%d ",temp.cost);
					vis[temp.id]=1;
					flag=1;
					break;
				}
			}
		}
		if(flag==0) printf("-1 ");//没有习题册可买,输出-1
	}
	return 0;
}

j–){
node temp=c[j];
c.pop_back();
if(!vis[temp.id]){
printf("%d “,temp.cost);
vis[temp.id]=1;
flag=1;
break;
}
}
}
if(flag==0) printf(”-1 ");//没有习题册可买,输出-1
}
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值