難易度評価

難易度を1〜10段階で評価できます。投票はあとから変更・取り消しできます。

難易度(投票) 未投票 (0票)

投票の分布

まだ投票はありません。

  1. Lv.10票
  2. Lv.20票
  3. Lv.30票
  4. Lv.40票
  5. Lv.50票
  6. Lv.60票
  7. Lv.70票
  8. Lv.80票
  9. Lv.90票
  10. Lv.100票

難易度の目安を見る ↗

ログインして難易度を投票

外部サイトへ移動します

リンク先の URL を確認してから開いてください。

別タブで開く

Incremental Machine

作成者 kammyu

難易度(作成者設定) Lv.5

難易度(投票) 未投票 (0票)

実行時間制限
2 秒
メモリ制限
512 MiB

まず、クエリによってどのように数列に加算されるかを考えます。

xx が 11 ずつ増えながら一方向に移動し、xx の分だけ足すことになります。

右方向に移動することに限定すると、以下のように表現することができます。

     #
    ##
   ###
  ####
 #####
######
######
######

ここで、これを以下のように A と B に分けて考えます。

     A
    AA
   AAA
  AAAA
 AAAAA
AAAAAA
BBBBBB
BBBBBB

考えやすくするために、考える区間を [l,r)[l,r) 、幅を W=r−lW=r-l 、B の高さを HH とします。

まず B から考えます。B は区間 [l,r)[l,r) に等しく HH だけ足しています。これは「imos法」によって管理することができます。

次に A を考えます。移動する方向を固定すると A も imos 法によって管理することができます。
具体的には、同じ配列に 22 回 imos 法を適用することで直角二等辺三角形を足すクエリを処理できます。

以上の議論と可算クエリしかないことから、右向きの A 、左向きの A 、B の可算クエリを別々に処理し、最後に足し合わせればよいです。

また、以下の考察により、Ai<NQ2≤8×1015A_i<NQ^2\le8\times10^{15} となることが分かるため、64bit64\text{bit} 整数型を用いることで AC を得ることができます。

  • クエリによる xx の増加量は高々 N−1N-1 である。
  • クエリは QQ 回なので、xx は高々 Q(N−1)Q(N-1) である。
  • 11 つのクエリによって AA のある要素に足される回数は高々 11 回である。

以上を適切に実装することで、O(N+Q)O(N+Q) でこの問題を解くことができました。

実装例(C++)

#include <bits/stdc++.h>
using namespace std;
int main()
{
  int N, Q;
  cin >> N >> Q;

  vector<long long> imo1L(N + 2, 0), imo1R(N + 2, 0), imo2L(N + 2, 0), imo2R(N + 2, 0);
  int p = 1;
  long long x = 0;

  while (Q--)
  {
    int t;
    cin >> t;
    if (p == t)
      continue;
    if (p < t)
    {
      imo2L[p]++, imo2L[t]--;
      imo1L[p] += x;
      x += t - p;
      imo1L[t] -= x;
    }
    else
    {
      imo2R[p]++, imo2R[t]--;
      imo1R[p] += x;
      x += p - t;
      imo1R[t] -= x;
    }
    p = t;
  }

  for (int i = 1; i <= N; i++)
    imo1L[i] += imo1L[i - 1] + (imo2L[i] += imo2L[i - 1]);
  for (int i = N; i >= 1; i--)
    imo1R[i] += imo1R[i + 1] + (imo2R[i] += imo2R[i + 1]);

  for (int i = 1; i <= N; i++)
    cout << imo1L[i] + imo1R[i] << " ";
  cout << endl;
}

ユーザー解説

ユーザー解説を書く

ユーザー解説はまだありません。