【团队赛组】2021-2022年度第三届全国大学生算法设计与编程挑战赛(秋季赛)—热身赛题解

A.这是一道压轴题

思路:把连续的0和1区间取出,两两相加区间长度,取最大

通过代码:

#include <bits/stdc++.h>
using namespace std;
int main() {
  int n;
  cin>>n;
  string s;
  cin >> s;
  vector<pair<int, int>> invter1, invter0;
  int l = 0, f = 0;
  for (int i = 1; i <= n; i++) {
    if (s[i - 1] == '1') {
      if (!l) {
        l = i;
      }
      if (f) {
        invter0.push_back(make_pair(f, i - 1));
        f = 0;
      }
    } else {
      if (!f) {
        f = i;
      }
      if (l) {
        invter1.push_back(make_pair(l, i - 1));
        l = 0;
      }
    }
  }
  if (l) {
    invter1.push_back(make_pair(l, n));
  }
  if (f) {
    invter0.push_back(make_pair(f, n));
  }
  vector<int> Len1, Len0;
  for (auto pair : invter0) {
    Len0.push_back(pair.second - pair.first + 1);
  }

  for (auto pair : invter1) {
    Len1.push_back(pair.second - pair.first + 1);
  }

  int ans0 = 0, ans1 = 0;
  if (Len0.size() == 1) {
    ans0 = Len0[0];
  }

  if (Len1.size() == 1) {
    ans1 = Len1[0];
  }

  for (int i = 0; i + 1 < Len0.size(); i++) {
    ans0 = max(Len0[i] + Len0[i + 1], ans0);
  }

  for (int i = 0; i + 1 < Len1.size(); i++) {
    ans1 = max(Len1[i] + Len1[i + 1], ans1);
  }

  cout << max(ans0, ans1) << endl;

  return 0;
}

B.这是一道大水题

思路:线段树保留两个信息,一个保留区间和,一个保留单点的信息,单点保留加入的区间和信息

通过代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Node {
  ll ls, rs;
  ll lz1, sum1, lz2, sum2;
} tr[800005];
void pushup1(ll k) {
  tr[k].sum1 = tr[k << 1].sum1 + tr[k << 1 | 1].sum1;
}

void pushup2(ll k) {
  tr[k].sum2 = tr[k << 1].sum2 + tr[k << 1 | 1].sum2;
}

void pushdown1(ll k) {
  if (tr[k].ls == tr[k].rs) {
    tr[k].lz1 = 0;
    return;
  }
  if (tr[k].lz1) {
    tr[k << 1].lz1 += tr[k].lz1;
    tr[k << 1 | 1].lz1 += tr[k].lz1;
    tr[k << 1].sum1 += (tr[k << 1].rs - tr[k << 1].ls + 1) * tr[k].lz1;
    tr[k << 1 | 1].sum1 +=
        (tr[k << 1 | 1].rs - tr[k << 1 | 1].ls + 1) * tr[k].lz1;
    tr[k].lz1 = 0;
  }
}

void pushdown2(ll k) {
  if (tr[k].lz2) {
    tr[k << 1].lz2 += tr[k].lz2;
    tr[k << 1 | 1].lz2 += tr[k].lz2;
    tr[k << 1].sum2 += (tr[k << 1].rs - tr[k << 1].ls + 1) * tr[k].lz2;
    tr[k << 1 | 1].sum2 +=
        (tr[k << 1 | 1].rs - tr[k << 1 | 1].ls + 1) * tr[k].lz2;
    tr[k].lz2 = 0;
  }
}

void build(ll k, ll l, ll r) {
  tr[k].lz1 = tr[k].lz2 = 0;
  tr[k].ls = l, tr[k].rs = r;
  if (l == r) {
    return;
  }
  ll mid = l + r >> 1;
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
}

void update1(ll k, ll l, ll r, ll w) {
  if (tr[k].ls >= l && tr[k].rs <= r) {
    tr[k].sum1 += (tr[k].rs - tr[k].ls + 1) * w;
    tr[k].lz1 += w;
    return;
  }
  pushdown1(k);
  ll mid = (tr[k].ls + tr[k].rs) >> 1;
  if (l <= mid) {
    update1(k << 1, l, r, w);
  }
  if (r > mid) {
    update1(k << 1 | 1, l, r, w);
  }
  pushup1(k);
}

void update2(ll k, ll l, ll r, ll w) {
  if (tr[k].ls >= l && tr[k].rs <= r) {
    tr[k].sum2 += (tr[k].rs - tr[k].ls + 1) * w;
    tr[k].lz2 += w;
    return;
  }
  pushdown2(k);
  ll mid = (tr[k].ls + tr[k].rs) >> 1;
  if (l <= mid) {
    update2(k << 1, l, r, w);
  }
  if (r > mid) {
    update2(k << 1 | 1, l, r, w);
  }
  pushup2(k);
}

ll getsum1(ll k, ll l, ll r) {
  if (tr[k].ls >= l && tr[k].rs <= r) {
    return tr[k].sum1;
  }
  pushdown1(k);
  ll mid = (tr[k].ls + tr[k].rs) >> 1;
  ll ans = 0;
  if (l <= mid) {
    ans += getsum1(k << 1, l, r);
  }
  if (r > mid) {
    ans += getsum1(k << 1 | 1, l, r);
  }
  return ans;
}

ll getsum2(ll k, ll x) {
  if (tr[k].ls == tr[k].rs) {
    return tr[k].sum2;
  }
  pushdown2(k);
  ll mid = (tr[k].ls + tr[k].rs) >> 1;

  if (x <= mid) {
    return getsum2(k << 1, x);
  }
  if (x > mid) {
    return getsum2(k << 1 | 1, x);
  }
}

int main() {
  ll n, m;
  scanf("%lld %lld", &n, &m);
  build(1, 1, n);
  while (m--) {
    ll op, l, r, w, k;
    scanf("%lld", &op);
    if (!op) {
      scanf("%lld %lld %lld", &l, &r, &w);
      update1(1, l, r, w);
      update2(1, l, r, (r - l + 1) * w);
    } else {
      scanf("%lld", &k);
      ll sum = tr[1].sum1;
      ll part = getsum2(1, k);
      printf("%lld\n", sum - part);
    }
  }
  return 0;
}

C.Chanllaging Problem
不会。

D.智慧数
思路:暴力枚举答案

#include <bits/stdc++.h>
using namespace std;
bool check(int x) {
  int ans = sqrt(x);
  ans *= ans;
  return ans == x;
}
bool acs(int s) {
  for (int i = 2; i * i <= s; i++) {
    if (s % i == 0) {
      if (check(s * i) || check(s / i * s)) {
        return true;
      }
    }
  }
  return false;
}
int main() {
  // int index = 0, i;
  // for (i = 8; index != 3000; i++) {
  //   if (acs(i)) {
  //     index++;
  //   }
  // }
  // cout << index << ' ' << i-1 << endl;
  int s;
  cin >> s;
  puts("7720");
  return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值