2022.10.08 总结

1. 洛谷 P8092

洛谷 P8092

题意#

有一个序列 a,每次操作选择两个相邻元素 ai,ai+1,并将它们的值 1,这样一次操作在答案中算作两次,请你求出最少需要多少次才能使得序列 a 中的所有元素相等。

思路#

48 分#

枚举最终元素,暴力修改序列,判断最后两个元素是否相等。

时间复杂度#

枚举最终元素,O(max(hi))

更改序列,O(n)

总时间复杂度为 O(max(hi)×n)

空间复杂度#

临时数组更改序列,O(n)

100 分#

从头到尾将序列修改成一个非递增序列,再从后往前将序列维护成元素全部相等,最后再判断一次元素是否相等。

时间复杂度#

序列总共遍历 3 次,O(3×n)

总共 t 组数据,总时间复杂度为 O(t×n)

空间复杂度#

用数组模拟更改序列,O(n)

代码#

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

int t, n, h[N];

int main(){
  cin >> t;
  while (t--) {
    cin >> n;
    for (int i = 1; i <= n; i++) {
      cin >> h[i];
    }
    long long cnt = 0;
    bool f = 0;
    for (int i = 2; i < n; i++) {  // 从前往后遍历
      if (h[i] < h[i - 1]) {
        continue;
      }
      cnt += 2 * (h[i] - h[i - 1]);
      h[i + 1] -= h[i] - h[i - 1], h[i] = h[i - 1];  // 更改序列
      if (h[i] < 0 || h[i + 1] < 0) {
        f = 1;
        break;
      }
    }
    for (int i = n - 1; i > 1; i--) {  // 从后往前遍历
      if (h[i] < h[i + 1]) {
        continue;
      }
      cnt += 2 * (h[i] - h[i + 1]);
      h[i - 1] -= h[i] - h[i + 1], h[i] = h[i + 1];  // 更改序列
      if (h[i] < 0 || h[i - 1] < 0) {
        f = 1;
        break;
      }
    }
    int p = h[1];
    for (int i = 1; i <= n; i++) {  // 判断是否相等
      if (h[i] != p) {
        f = 1;
        break;
      }
    }
    if (f) {
      cnt = -1;
    }
    cout << cnt << endl;
  }
  return 0;
}

2. 洛谷 P8184

洛谷 P8184

题意#

有两个序列 a,b,每次可以选择一个 ai 并向左移动一些位置,请你求出最少需要多少次可以使得 a 变成 b

思路#

70 分#

记录下序列 b 的每个元素的编号,将 a 序列的元素替换成编号,再进行插入排序,将编号从小到大排序。

时间复杂度#

记录编号,O(n)

替换成编号,O(n)

插入排序,O(n×n)

总时间复杂度为 O(n×n)

空间复杂度#

临时数组记录编号,O(n)

100 分#

双指针,a 序列一个,b 序列一个,将元素进行一一对应。

时间复杂度#

双指针,O(n)

空间复杂度#

一个标记数组记录是否出现过,O(n)

代码#

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

int n, a[N], b[N], c, cnt;
bool f[N];

int main(){
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 1; i <= n; i++) {
    cin >> b[i];
  }
  for (int i = 1, j = 1; max(i, j) <= n; ) {
    if (f[b[j]]) {  // 如果已经被插入到序列中
      continue;
    }
    if (a[i] != b[j]) {  // 两个元素不相等
      cnt++, f[b[j]] = 1;  // 需要插入 b[j],并标记 b[j] 被插入过
      j++;
    } else {
      f[a[i]] = 1;  // 这个元素被插入过
      while (i <= n && f[a[i]]) {  // 往后找到第一个没有被插入过的
        i++;
      }
      j++;
    }
  }
  cout << cnt;
  return 0;
}

作者:cn

出处:https://www.cnblogs.com/chengning0909/p/17173877.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   chengning0909  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 百万级群聊的设计实践
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示