ABC 213 题解

ABC 213 题解

这场比赛出的比较良心 QAQ

A

XOR 在 C++ 中代表异或,可以用 ^ 表示。

XOR

a a a b b b 异或是这样的:

  • 首先,把 a a a b b b 转换成 2 2 2 进制。高位补 0 0 0

  • 将它们逐位比较,相同的为假,不相同为真

  • 再转 10 10 10 进制。

它的一个重要特性是:交换

详细来说,是这样的:

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,其中有两个参数 firstsecond

这里,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,500001,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:咕咕咕

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值