結果

提出番号 980
提出者 ei1333
言語 C++
提出日時 2017-08-02 00:16:12
問題名 (25)Range of Influence
結果 AC
点数 100%

テストケース

テストケース 結果 得点 実行時間 メモリ使用量
1 AC 100% 19ms 145536KB
2 AC 100% 25ms 145536KB
3 AC 100% 17ms 145520KB
4 AC 100% 25ms 145584KB
5 AC 100% 257ms 195408KB
6 AC 100% 237ms 207024KB
7 AC 100% 2474ms 841648KB
8 AC 100% 467ms 279888KB
9 AC 100% 2807ms 914512KB
10 AC 100% 2933ms 914512KB
11 AC 100% 4484ms 914512KB
12 AC 100% 17ms 145536KB
13 AC 100% 2867ms 914512KB
14 AC 100% 18ms 145536KB
15 AC 100% 4414ms 914512KB
16 AC 100% 4112ms 914512KB
17 AC 100% 22ms 145536KB
18 AC 100% 22ms 145536KB

ソースコード

#include<bits/stdc++.h>

using namespace std;

const int INF = 1 << 30;

template< typename T >
struct SegmentTree
{
  vector< T > seg;
  int sz;

  SegmentTree(int n)
  {
    sz = 1;
    while(sz < n) sz <<= 1;
    seg.assign(2 * sz - 1, INF);
  }

  T merge(T a, T b)
  {
    return (min(a, b));
  }

  void set(int k, int x)
  {
    seg[k + sz - 1] = x;
  }

  void build()
  {
    for(int k = sz - 2; k >= 0; k--) {
      seg[k] = merge(seg[2 * k + 1], seg[2 * k + 2]);
    }
  }

  T rmq(int a, int b, int k, int l, int r)
  {
    if(a >= r || b <= l) return (INF);
    if(a <= l && r <= b) return (seg[k]);
    return (merge(rmq(a, b, 2 * k + 1, l, (l + r) >> 1),
                  rmq(a, b, 2 * k + 2, (l + r) >> 1, r)));
  }

  T rmq(int a, int b)
  {
    return (rmq(a, b, 0, 0, sz));
  }

  void update(int k, T x)
  {
    k += sz - 1;
    seg[k] = x;
    while(k > 0) {
      k = (k - 1) >> 1;
      seg[k] = merge(seg[2 * k + 1], seg[2 * k + 2]);
    }
  }
};

int N, A[3000], B[3000];
int dp[3000][3000];
int sum[3005];

int main()
{
  cin >> N;
  for(int i = 0; i < N; i++) cin >> A[i];
  for(int i = 0; i < N; i++) cin >> B[i];

  for(int i = 0; i < N; i++) sum[i + 1] += sum[i] + A[i];

  fill_n(*dp, 3000 * 3000, INF);
  vector< SegmentTree< int > > latte(N, SegmentTree< int >(N)), malta(N, SegmentTree< int >(N));

  // l(low≦l≦k)    := dp[j][l-1]+B[l]
  // l(j≦l≦low-1)  := dp[l+1][k]+B[l]
  // ここで k と j は定数なので kとjに関するセグ木があればよくて

  auto update = [&](int x, int y)
  {
    if(y + 1 < N) latte[x].update(y + 1, dp[x][y] + B[y + 1]);
    if(x - 1 >= 0) malta[y].update(x - 1, dp[x][y] + B[x - 1]);
  };

  for(int i = 0; i < N; i++) {
    dp[i][i] = B[i];
    update(i, i);
  }

  for(int i = 2; i <= N; i++) {
    for(int j = 0; j <= N - i; j++) {
      int k = j + i - 1; // [j, k]

      // sum1 >= sum2

      int low = j, high = k + 1;
      while(high - low > 0) {
        int mid = (low + high) >> 1;
        int sum1 = sum[mid] - sum[j];
        int sum2 = sum[k + 1] - sum[mid + 1];
        if(sum1 >= sum2) high = mid;
        else low = mid + 1;
      }
      dp[j][k] = min(dp[j][k], latte[j].rmq(low, k + 1));
      dp[j][k] = min(dp[j][k], malta[k].rmq(j, low));
      update(j, k);
    }
  }

  cout << dp[0][N - 1] << endl;
}