acwing 第24场周赛
本次的周赛有三道题目:模拟,枚举,模拟
acwing 4070. 异或
题目描述
解题思路
很简单的模拟,输入的时候记录最大值和最后一个输入,甚至连数组都不用开
代码
#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. 国际象棋
题目描述
解题思路
棋盘上有车和马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.
题目描述
解题思路
题目中的知识点总数只有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;
}