Atcoder Beginner Contest 236 ABC 代码风格 格式#ifdef#else#endif ios::sync_with_stdio tie 异或 map容器 vector容器

Atcoder Beginner Contest 236 ABC 代码风格 格式#ifdef#else#endif ios::sync_with_stdio tie 异或 map容器 vector容器
8分钟a了前两个,然后第三个,头卡掉了。(记录一下悲惨的经历。
就继续磨题解吧。

琢磨题解的时候发现了这个:

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

学习一下,形式:

#ifdef 标识符
程序段1
#else
程序段2
#endif

意思是:当标识符已经被定义过(一般使用#define命令定义)则对程序段1进行编译,否则编译程序段2。

浅显理解一下

继续优化一下c++代码:

ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);

关于这个东西。
sync_with_stdio:是否兼容stdio的开关,c++中既可以使用printf也可以使用cout,也可以混用这两个输出方式。
关闭iostream的输入输出缓存,让cin和cout的效率与scanf和printf相差不大。

来看第一题:
输入一个字符串,交换第a和第b两个位置的字符,然后输出。
代码如下:

#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  string s;
  cin >> s;
  int a, b;
  cin >> a >> b;
  swap(s[a - 1], s[b - 1]);
  cout << s << '\n';
  return 0;
}

一点点代码风格,头文件,using namespace std;,和题解代码换行分开。
值得学习,使用纯c++,加上ios::sync_with_stdio(false);cin.tie(0);以提高输入输出效率。
交换字符,使用函数swap(a,b).

第二题,题意:输入n,从1到n都有四个数字,其中有一个数字有三个,输出这个数字。
我第一个思路是计数,cnt=3的那个数字输出,当然这样需要遍历两遍。

不妨考虑一下数学方法,一个数的偶数次异或结果是0,这不,最后不就只剩下那个3个的数了吗?既节省时间,又节省空间。太棒了!

代码:

/**
 *    author:  tourist
 *    created: 23.01.2022 15:00:42       
**/
#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  int x = 0;
  for (int i = 0; i < 4 * n - 1; i++) {
    int y;
    cin >> y;
    x ^= y;
  }
  cout << x << '\n';
  return 0;
}

值得学习的地方就是 x^=y 这个数学式子,巧妙的等效了一个开数组,一层遍历。

第三题就是卡掉脑袋的题。最高效的是用vector map做,还是使用的不熟练,继续巩固。

第三题是先输入n个字符串,再输入m个字符串,如果m中有n中的字符串,输出Yes,否则输出No。

代码:

/**
 *    author:  tourist
 *    created: 23.01.2022 15:01:51       
**/
#include <bits/stdc++.h>

using namespace std;

#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<bool> res(n, false);
  map<string, int> mp;
  for (int i = 0; i < n; i++) {
    string s;
    cin >> s;
    mp[s] = i;
  }
  for (int j = 0; j < m; j++) {
    string s;
    cin >> s;
    res[mp[s]] = true;
  }
  for (int i = 0; i < n; i++) {
    cout << (res[i] ? "Yes" : "No") << '\n';
  }
  return 0;
}

首先,忘了定义vector最常用的方法了???

//定义具有10个整型元素的向量,且给出的每个元素初值为1
vector<bool> res(n,0);
//意思是定义vector bool类型 res 大小为n 其中元素初始值为0

还不止这个,c++stl中很重要的map!

开始学习map容器(暴露自己又菜又懒了):
map是stl里的一个关联容器,,提供一对一的hash映射。(key与value)
map的底层结构是红黑树,红黑树对数据自动排序,故map中的元素自动有序。
map头文件#include< map> 当然万能头也行。
然后定义:std::map<string,int> personnel;
其中第一个类型是关键字的类型,第二个是存储对象的类型,本题就定义了string类型的关键字作为索引,并拥有相关联的指向int的指针。

这个代码还有一个很巧妙的地方,
string s;
cin >> s;
mp[s] = i;
使用string做索引,使用i做数据存储。想法很赞。
接下来的思路是,输入m的字符串,里面存在的使用res标记,最后输出。
其中还有值得学习的东西,最后的三目运算符
输出cout << (res[i] ? “Yes” : “No”);
要使用三目运算符把一个if-else的判断语句变成一句话,代码更简洁。

上一篇:Java基础学习笔记——面向对象


下一篇:AcWing 278 数字组合 题解 (动态规划—DP—背包问题)