ARC170 – B – 题解

问题

Problem Statement

给出一个长度为 N 的序列 A ,其由 1\textbf{10} 之间的整数组成。

如果满足以下条件,那么三元组 (l,r)1\leq l \leq r\leq N )是“好数对”:

  • 序列 (A_l,A_{l+1},\ldots,A_r) 包含长度为 3 的等差子序列。换言之,存在整数对 (i,j,k)l \leq i < j < k\leq r ),使得 A_j - A_i = A_k - A_j

求“好数对”的个数。

Constraints

  • 3 \leq N \leq 10^5
  • 1\leq A_i \leq 10
  • 所有输入均为整数。

Input

输入格式如下:

  • N
  • A_1 \ldots A_N

Output

输出“好数对”的个数。

解法

思路

利用双指针的思想,将 lr 分别看作左右指针。

考虑到 A_i 的范围很小,可以直接使用队列存储三元组的第一个数;再利用前缀和存储每个数的总数,用于处理三元组的第二个数。

然后只需要从头开始遍历 r ,找三元组的第三个数。每遍历到一个数,就将 r 的值推入到这个数对应的队列内,紧接着在符合条件的非空队列中提取首值,然后计算对应的中间值,利用之前保存的前缀和判断从 l+1r-1 的区间内是否存在中间值。

如果存在,说明目前从 lr 的区间中存在符合题意的三元组,再根据 A_rA_n 的距离确定当前 l 对应的三元组总数量,并将其添加到答案中;然后弹出 l 所在队列的首值(弹出的值应该正好为l),自增 l 后重复上述步骤,直到中间值不存在或对应队列被清空。

遍历完 r 之后即可输出答案,一定记得开 long long ,否则会溢出。时间复杂度为 O(n)

实现

按如下方式开前缀和数组和队列:

int r[11][100010];
queue<int> st[11];

以下为实现:

--snip--
void solve() {
  int ptr = 1; // ptr 表示 l 的位置
  for (int i = 1; i <= n; ++i) {
    st[arr[i]].push(i); // 在对应队列推入当前的 r 值
    for (int j = 1; j <= 10; ++j) {
      // 遍历队列,若队列为空或中间值不为整数则跳过
      if (st[j].empty() || (j + arr[i]) % 2 != 0) continue;
      int p = st[j].front(); // 指定三元组第一个数的位置
      // 通过前缀和判定中间值是否存在
      while ((j + arr[i]) % 2 == 0 &&
             r[(j + arr[i]) / 2][i - 1] - r[(j + arr[i]) / 2][p] > 0) {
        ans += n - i + 1; // 从 (l, r) 到 (l, n) 都包括此三元组
        // 弹出左指针对应的元素,并令其右移
        st[arr[ptr]].pop();
        ptr++;
        if (st[j].empty()) break; // 对应队列为空时跳出 while 循环
        p = st[j].front();
      }
    }
  }
}

int main(){
  cin >> n;
  for (int i = 1; i <= n; ++i) {
    cin >> arr[i];
    // 根据输入值处理前缀和,非输入值的前缀和维持不变
    for (int j = 1; j <= 10; ++j) {
      if (j == arr[i])
        r[arr[i]][i] = r[arr[i]][i - 1] + 1;
      else
        r[j][i] = r[j][i - 1];
    }
  }
  solve();
  cout << ans << endl;
  return 0;
}
Tips: 评论支持 Markdown 语法哦~
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇