【算法小白周赛1E】ET表题解与代码(算法与数据结构刷题计划)

题目链接:https://www.starrycoding.com/contest/3/E

题目描述

小e发明了一种奇怪的数据结构------ET表,这一奇怪的数据结构有以下两种奇怪的操作:

  • 将前 i i i 个数减去 k k k。
  • 将后 i i i 个数减去 k k k。

为了测试ET表的性能,小e找来了一个长度为 n n n 数组 a a a,现在需要判断能否通过ET表的这两种操作将这个数组的每一个数都变成 0 0 0,以及最少的操作次数。

输入格式

第一行为一个正整数 T T T ( 1 ≤ T ≤ 1 0 6 1 \le T \le 10^6 1≤T≤106 ),表示测试用例个数。

对于每个测试用例:

第一行为一个正整数 n n n ( 1 ≤ n ≤ 1 0 6 1 \le n \le 10^6 1≤n≤106 ),表示数组长度;

第二行包含 n n n 个正整数 a 1 ... a n a_1 \ldots a_n a1...an ( 1 ≤ a i ≤ 1 0 6 1 \le a_i \le 10^6 1≤ai≤106 )

数据保证 ∑ n ≤ 1 0 6 \sum{n} \le 10^6 ∑n≤106。

输出格式

每个测试用例的输出一行:

  • 如果可以通过一定次数的ET表操作使数组的所有元素都等于零,输出一个正整数,表示最少的操作次数。
  • 否则输出 − 1 -1 −1。

样例 #1

样例输入 #1

复制代码
4
3
1 2 1
3
2 3 2
5
19 1 9 8 10
6
1 1 4 5 1 4

样例输出 #1

复制代码
2
3
4
-1

说明/提示

对于样例第二组数据 2 , 3 , 2 2, 3, 2 2,3,2

  • 选择 i = 3 , k = 1 i = 3, k = 1 i=3,k=1 进行操作一,数组变为 1 , 2 , 1 1, 2, 1 1,2,1
  • 选择 i = 2 , k = 1 i = 2, k = 1 i=2,k=1 进行操作一,数组变为 0 , 1 , 1 0, 1, 1 0,1,1
  • 选择 i = 2 , k = 1 i = 2, k = 1 i=2,k=1 进行操作二,数组变为 0 , 0 , 0 0, 0, 0 0,0,0

成功归零,共操作 3 3 3 次。

对于样例第三组数据 19 , 1 , 9 , 8 , 10 19, 1, 9, 8, 10 19,1,9,8,10

  • 选择 i = 1 , k = 18 i = 1, k = 18 i=1,k=18 进行操作一,数组变为 1 , 1 , 9 , 8 , 10 1, 1, 9, 8, 10 1,1,9,8,10
  • 选择 i = 1 , k = 2 i = 1, k = 2 i=1,k=2 进行操作二,数组变为 1 , 1 , 9 , 8 , 8 1, 1, 9, 8, 8 1,1,9,8,8
  • 选择 i = 3 , k = 1 i = 3, k = 1 i=3,k=1 进行操作一,数组变为 0 , 0 , 8 , 8 , 8 0, 0, 8, 8, 8 0,0,8,8,8
  • 选择 i = 3 , k = 8 i = 3, k = 8 i=3,k=8 进行操作二,数组变为 0 , 0 , 0 , 0 , 0 0, 0, 0, 0, 0 0,0,0,0,0

成功归零,共操作 4 4 4 次。

对于样例第四组数据,无论如何也无法将其归零。

题解

其实所谓的ET表操作,其实就是对数组的某一长度的前、后缀进行区间减去某个数的操作,此时我们应该想到非常擅长进行区间操作的好东西------差分。

建立差分数组 d d d,对于数组 l , r l,r l,r 的修改就等效于对差分数组的 d l d_l dl 和 d r + 1 d_{r+1} dr+1 进行修改,此时的ET表操作就变成了:

  • 将 d 1 d_1 d1 减少 k k k,将 d i + 1 d_{i+1} di+1 增加 k k k,
  • 将 d n − i + 1 d_{n-i+1} dn−i+1 减少 k k k,将 d n + 1 d_{n+1} dn+1 增加 k k k,

且此时 d n + 1 d_{n+1} dn+1 对数组 a a a 不会有任何影响,所以对它的操作可以忽略,而我们的最终目的------将数组 a a a 归零也就等效于将 d 1 ... d n d_1 \ldots d_n d1...dn 归零。所以在判断是否可行是,我们只需要计算差分数组中所有小于 0 0 0 的数的绝对值之和 s s s,将这个总和与 d 1 d_1 d1 进行比较,如果大于 d 1 d_1 d1 则说明无法完成归零。计算最少操作次数则贪心的只对 d 2 ... d n d_2 \ldots d_n d2...dn 中每个非 0 0 0 的进行一次操作,最后特判一下进行了上述操作后 d 1 d_1 d1 是否已经归零,也就是 s s s 是否等于 d 1 d_1 d1 来确定是否还要进行一次操作使 d 1 d_1 d1 归零。

cpp 复制代码
void solve()
{
    int n;
    cin >> n;
    vector<int> a(n + 1);
    vector<int> d(n + 1, 0);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        d[i] = a[i] - a[i - 1]; // 差分
    }
    int s = 0, ans = 0;
    for (int i = 2; i <= n; i++)
    {
        if (d[i] < 0)
        {
            s += abs(d[i]); // 对于差分数组中小于0的进行操作一,
            ans++;          // 操作次数+1,并记录会对d[1]产生的影响
        }
        else if (d[i] > 0)
        {
            ans++; // 对于大于0的进行一次操作二
        }
    }
    if (s > d[1]) // d[1]不足以完成足够的操作一
    {
        cout << -1 << endl;
        return;
    }
    if (s < d[1]) // 当前进行的操作一不足以将d[1]归零
    {
        ans++;
    }
    cout << ans << endl;
    return;
}

StarryCoding - 编程开发新手村,非常适合新手小白的一个网站,推荐给大家~

5月1日晚上还有一场入门教育赛,欢迎来玩:https://www.starrycoding.com/contest/5

相关推荐
Hi李耶1 分钟前
【LeetCode】9-回文数
算法·leetcode·职场和发展
红叶舞2 分钟前
基于线段树的数据结构
数据结构·python·算法
断点之下1 小时前
从“理扑克牌”到“分组优化”——直接插入排序与希尔排序详解
数据结构·算法·排序算法
起个破名想半天了1 小时前
算法与数据结构之DFS深度优先遍历
数据结构·算法·深度优先
李伟_Li慢慢1 小时前
凸包算法
人工智能·算法
徐礼昭|商派软件市场负责人1 小时前
AI Agent 蜂群协作与经验基因化:从单体执行到自组织系统的工程路径
大数据·人工智能·算法·智能体·多agent
来者皆善1 小时前
【位RAW图像处理五】任意位深位图像的中值模糊快速实现及其应用。
图像处理·人工智能·算法
happyprince1 小时前
第三观 · 深刻不忘观 —— AngelSpec 哲学与升华
人工智能·算法
鱼子星_1 小时前
【C++】深入剖析list:list及其双向迭代器实现
开发语言·数据结构·c++·笔记·stl·list
脚踏实地皮皮晨2 小时前
003002004_WPF Panel 基类 官方类定义
开发语言·windows·算法·c#·wpf·visual studio