ABC 213 题解
这场比赛出的比较良心 QAQ
A
XOR 在 C++ 中代表异或,可以用 ^ 表示。
XOR
a
a
a 和
b
b
b 异或是这样的:
它的一个重要特性是:交换。
详细来说,是这样的:
void swap(int &a, int &b){
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
原理:
- 首先,第一行
a = a ^ b 请自行理解。 - 第二行
b = a ^ b 表示,如果
b
b
b 和
a
a
a 在这个位上相同,那么
a
a
a 肯定为
0
0
0,那么
b
b
b 为
0
0
0 就是
0
0
0,反之亦然。于是,
b
b
b 等于
a
a
a。 - 第三行与第二行同理,可以看出,
a
=
b
a=b
a=b。所以,起到了交换的作用。
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
int a, b;
cin >> a >> b;
cout << (a ^ b) << endl;
return 0;
}
B
啊这这道题很水。
主要就是 sort 。我们需要定义一个结构体 node ,其中有两个参数 first 和 second 。
这里,STL 已经给出了一个写法:pair<type a, type b> 。
所以,first 代表得分,second 代表编号。
然后就没了。
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
int n;
cin >> n;
pair<int, int> a[n];
for(int i = 0;i < n;i++){
cin >> a[i].first;
a[i].second = i;
}
sort(a, a + n);
cout << a[n - 2].second + 1 << endl;
return 0;
}
C
好的这道题比较有趣。
首先,不难得出结论:操作后任意一行一列都至少有一个点。
然后,我们想:这不就是离散化吗?
离散化就是这样的:
1
,
20
,
300
,
4000
,
50000
→
1
,
2
,
3
,
4
,
5
1,20,300,4000,50000 \to 1,2,3,4,5
1,20,300,4000,50000→1,2,3,4,5
这就是排名。
怎么做?
- 我们需要
sort 一下。 - 我们需要设排名
t
=
1
t=1
t=1。
- 我们将它们事先存好的编号给一个一个扔进排名数组里,排名为
t
t
t。
- 如果后面的数等于前面的数,
t
t
t 不加
1
1
1。
- 否则,
t
t
t 加
1
1
1。
代码:
int t = 1, t1 = 1;
for(int i = 0;i < n;i++){
l[d[i].second] = t;
l1[d1[i].second] = t1;
t++, t1++;
if(i == n - 1){
continue;
}
if(d[i].first == d[i + 1].first){
t--;
}
if(d1[i].first == d1[i + 1].first){
t1--;
}
}
注意:值一样的时候必须排名相同!
Code:
#include <bits/stdc++.h>
#define int long long
using namespace std;
signed main(){
int a, b, n;
cin >> a >> b >> n;
pair<int, int> d[n], d1[n];
for(int i = 0;i < n;i++){
cin >> d[i].first >> d1[i].first;
d[i].second = i, d1[i].second = i;
}
sort(d, d + n), sort(d1, d1 + n);
int l[n], l1[n];
int t = 1, t1 = 1;
for(int i = 0;i < n;i++){
l[d[i].second] = t;
l1[d1[i].second] = t1;
t++, t1++;
if(i == n - 1){
continue;
}
if(d[i].first == d[i + 1].first){
t--;
}
if(d1[i].first == d1[i + 1].first){
t1--;
}
}
for(int i = 0;i < n;i++){
cout << l[i] << " " << l1[i] << endl;
}
return 0;
}
D
我们看一下两个条件:
- 如果有没有去过的连着这个点的边,那么去最小的。
- 否则,去这个点第一次出现时,它上一个点。
因为这是一棵树,所以它可以简化为:
- 如果有没有访问过的子节点,访问最小的。
- 否则,去它的父亲节点。
因为第一次出现肯定是一个节点往下走的,所以是它的父亲节点。
这不是树上 DFS 吗?
模拟即可。
Code:
#include <bits/stdc++.h>
using namespace std;
vector<int> gv[200001];
void add_edge(int u, int v){
gv[u].push_back(v);
gv[v].push_back(u);
}
void dfs(int fa, int n){
cout << n << " ";
for(int i = 0;i < gv[n].size();i++){
if(gv[n][i] == fa){
continue;
}
dfs(n, gv[n][i]);
cout << n << " ";
}
}
int main(){
int n;
cin >> n;
for(int i = 0;i < n - 1;i++){
int u, v;
cin >> u >> v;
add_edge(u, v);
}
for(int i = 1;i <= n;i++){
sort(gv[i].begin(), gv[i].end());
}
dfs(0, 1);
return 0;
}
E、F、G:咕咕咕
|