AtCoder Beginner Contest 187

导读:
简单的题目,只说明题意,或者直接说明结论
下面的难题,会做详细的解释和证明
立个flag,在座的大佬们做个见证:一个月刷60场ABC,现在2021/6/24,第九天,已打卡十三场。

A - Large Digits

输出两个三位数每一位的数字和中较大的一个

void work()
{
  int a, b; cin >> a >> b;
  cout << max(a % 10 + a / 10 % 10 + a / 100, b % 10 + b / 10 % 10 + b / 100) << endl;
}

B - Gentle Pairs

横坐标之差大于等于纵坐标之差

void work()
{
  int n; cin >> n;
  int a[1010], b[1010];
  for (int i = 1; i <= n; i ++ )
    cin >> a[i] >> b[i];
  int ans = 0;
  for (int i = 1; i < n; i ++ )
    for (int j = i + 1; j <= n; j ++ )
    {
      if (abs(a[i] - a[j]) >= abs(b[i] - b[j]))
        ans ++;
    }
  cout << ans << endl;
}

C - 1-SAT

问是已经出现了加!和不加!同一个字符串。
拿到这题第一印象就是trie树,结果,算了,就这一点,直接暴力就完事了。

void work()
{
  int n; cin >> n;
  unordered_map<string, bool> mp;
  while (n -- )
  {
    string s; cin >> s;
    if (s[0] == '!')
    {
      string t = s.substr(1);
      if (mp.count(t))
      {
        cout << t << endl;
        return;
      }
      mp[s] = true;
    }
    else
    {
      if (mp.count("!" + s))
      {
        cout << s << endl;
        return;
      }
      mp[s] = true;
    }
  }
  cout << "satisfiable" << endl;
}

D - Choose Me

思维题啊,我欠缺的就是这种题目
如果再当前位置做演讲,结果就是B加上a+b,如果不做演讲,那就是A加上a
题目让我们输出使B成绩大于A的最小演讲次数。
假设一开始一次演讲都没做,也就是说sum为n个a的和,这也是A与B之间的差距,我们将这个sum定义为A与B之间的分数差距,那么我们每做一次演讲,首先本来给A的a,会变成B的投票,先-x,差距小了x,然后,因为票a+b都投给了B,所以,A的差距优惠减去(a+b)了。
所以我们贪心的每次减去最大的x+x+y,知道sum小于0,就是A的成绩小于B的时候了。

#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
int main()
{
  ll n; cin >> n;
  ll sum = 0;
  vector<ll> v;
  for (int i = 0; i < n; i ++ )
  {
    ll x, y; scanf("%lld%lld", &x, &y);
    sum += x;
    v.push_back(x + x + y);
  }
  sort(v.begin(), v.end());
  while (sum >= 0)
  {
    sum -= v.back();
    v.pop_back();
  }
  cout << n - v.size() << endl;
  return 0;
}

E - Through Path

这题最关键的地方就是对a能够到达且不会通过b的地方+x,
我们可以想到a能到达的地方,但是b不能到达的地方起始就是b这个点,将树分为两部分,看a在下部,那就是a的这颗子树全都加x,否则剩余部分加x从b这个位置-x。
运用的就是树形前缀和

#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
const int N = 200010;
int n;
ll sum[N];
int main()
{
  cin >> n;
  //存图
  vector<vector<int>> v(n + 1);
  vector<pair<int, int> > edge(n + 1);
  for (int i = 1; i < n; i ++ )
  {
    int a, b; scanf("%d%d", &a, &b);
    v[a].push_back(b);
    v[b].push_back(a);
    edge[i] = {a, b};
  }
  // 宽搜给每个点一个深度
  queue<int> q;
  q.push(1);
  vector<int> depth(n + 1, -1);
  depth[1] = 1;
  while (!q.empty())
  {
    int x = q.front(); q.pop();
    for (int y : v[x])
    {
      if (depth[y] != -1) continue;
      depth[y] = depth[x] + 1;
      q.push(y);
      // printf("x = %d, depth[x] = %d, y = %d, depth[y] = %d\n", x, depth[x], y, depth[y]);
    }
  }
  // for (int i = 1; i <= n; i ++ ) cout << depth[i] << " "; cout << endl;
  int Q; cin >> Q;
  while (Q -- )
  {
    int t, e, x; scanf("%d%d%d", &t, &e, &x);
    int a = edge[e].first, b = edge[e].second;
    if (t == 2) swap(a, b);
    // cout << a << " " << b << endl;
    if (depth[a] < depth[b])  sum[1] += x, sum[b] -= x;
    else sum[a] += x;
    // for (int i = 1; i <= n; i ++ ) cout << sum[i] << " "; cout << endl;
  }
  vector<ll> ans(n + 1);
  ans[1] = sum[1];
  q.push(1);
  vector<bool> vis(n + 1, false);
  vis[1] = true;
  while (q.size())
  {
    int x = q.front();
    q.pop();
    for (int y : v[x])
    {
      if (vis[y]) continue;
      ans[y] = ans[x] + sum[y];
      vis[y] = true;
      q.push(y);
    }
  }
  for (int i = 1; i <= n; i ++ )
    printf("%lld\n", ans[i]);
  return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值