Problem:
力持ち
力持ちたちが集う力持ち学園がありました。力持ち学園の運動会では、力持ちたちが隊列を組んで行進します。
力持ちたちは常に自分たちの力を誇示したい一方で、彼らの大半は自分で歩きたくありません。そこで彼らの一部が一番下になり、その上に大勢の人を縦一列に持ちあげて歩くことで、実際に歩く人数を減らそうと考えました。
はじめに、
N
人の力持ちは地面の上に横一列に並んでいて、それぞれ左側から １,２,３,...,
N
と通し番号で呼ばれています。通し番号
i
の力持ちの体重は
w
i
で最大
c
i
の重量まで持つことができます。
力持ちは、以下の条件をすべて満たすときだけ、隣に立っている左右どちらかの力持ちを持ちあげることができます。
自分の上下には力持ちはいない。つまり、誰かに持ち上げられてもいないし、誰かを持ちあげてもいない。
隣の力持ちの体重が、自分が持つことのできる最大の重量以下である。ただし、隣の力持ちが既に誰かを持ち上げているなら、縦に積み上がった力持ちたちの体重の合計が、自分が持つことのできる最大の重量以下でなければならない。
例えば、次のような３人の力持ちの隊列を考えてみましょう。
下図のように、２の力持ちが持つことのできる重さが
w
3
以上のとき、２の力持ちは３の力持ちを持ちあげることができます。続いて、１の力持ちが持つことのできる重さが
w
2
+
w
3
以上のとき、１の力持ちは２の力持ちを持ちあげることができます。
→
また、下図のように３の力持ちが２の力持ちを持ちあげた場合は、１の力持ちの隣が、２の力持ちを持った３の力持ちになるので、１の力持ちは３の力持ちを持ちあげることができます。
→
２の力持ちが、下の図のように１と３の力持ちを両方持つことはできません。
力持ち学園の専属プログラマーとして、一番下で歩くことになる最小の人数を求めてください。
入力
入力は以下の形式で与えられる。
N
c
1
w
1
c
2
w
2
:
c
N
w
N
1 行目に力持ちの人数
N
(1 ≤
N
≤ 1000) が与えられる。続く
N
行に
i
番目の力持ちが持てる重量の最大値
c
i
(1 ≤
c
i
≤ 100000) と体重
w
i
(1 ≤
w
i
≤ 100000) が与えられる。
出力
最小の人数を１行に出力する。
入出力例
入力例１
3
150 120
100 50
80 100
出力例１
1
入力例２
8
50 100
20 20
30 20
90 50
140 30
30 60
59 120
10 10
出力例２
3

Submitted solutions:

code_snippet: // competitive-verifier: PROBLEM
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#if !defined(ATCODER) && !defined(EVAL)
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m) - 1; i >= int(n); --i)
#define FORL(i, m, n) for (std::int64_t i = (m); i < std::int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
struct increment_impl {
    template <class T>
    const increment_impl &operator>>(std::vector<T> &v) const {
        for (auto &x : v) ++x;
        return *this;
    }
} Inc;
struct decrement_impl {
    template <class T>
    const decrement_impl &operator>>(std::vector<T> &v) const {
        for (auto &x : v) --x;
        return *this;
    }
} Dec;
struct sort_impl {
    template <class T>
    const sort_impl &operator>>(std::vector<T> &v) const {
        std::sort(v.begin(), v.end());
        return *this;
    }
} Sort;
struct unique_impl {
    template <class T>
    const unique_impl &operator>>(std::vector<T> &v) const {
        std::sort(v.begin(), v.end());
        v.erase(std::unique(v.begin(), v.end()), v.end());
        return *this;
    }
} Uniq;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
/// @brief 累積和
template <class T = std::int64_t>
struct prefix_sum {
    prefix_sum(int _n) : n(_n), data(_n + 1) {}
    template <class U>
    prefix_sum(const std::vector<U> &v) : n(v.size()), data(v.size() + 1) {
        for (int i = 0; i < n; ++i) data[i] = v[i];
        build();
    }
    void build() {
        for (int i = n - 1; i >= 0; --i) data[i] += data[i + 1];
    }
    T get(int k) const {
        assert(0 <= k && k < n);
        return data[k] - data[k + 1];
    }
    void set(int k, int x) { data[k] = x; }
    void add(int k, int x) { data[k] += x; }
    T sum(int r) const {
        assert(0 <= r && r <= n);
        return data[0] - data[r];
    }
    T sum(int l, int r) const {
        assert(0 <= l && l <= r && r <= n);
        return data[l] - data[r];
    }
    int min_left(T x) const { return min_left(0, x); }
    int min_left(int l, T x) const {
        assert(0 <= l && l <= n);
        int left = l, right = n + 1;
        while (right - left > 1) {
            int mid = (left + right) / 2;
            (data[l] - data[mid] >= x ? right : left) = mid;
        }
        return right;
    }
    int max_right(T x) const { return max_right(n, x); }
    int max_right(int r, T x) const {
        assert(0 <= r && r <= n);
        int left = -1, right = r;
        while (right - left > 1) {
            int mid = (left + right) / 2;
            (data[mid] - data[r] >= x ? left : right) = mid;
        }
        return left;
    }
  private:
    int n;
    std::vector<T> data;
};
int main(void) {
    int n;
    cin >> n;
    vector<int> c(n), w(n);
    rep (i, n) cin >> c[i] >> w[i];
    prefix_sum<ll> ps(w);
    vector dp(n + 1, vector(n + 1, 0));
    repn (d, n) {
        rep (l, n) {
            int r = l + d;
            if (r > n)
                break;
            dp[l][r] = r - l;
            FOR (m, l + 1, r) chmin(dp[l][r], dp[l][m] + dp[m][r]);
            if (dp[l][r - 1] == 1 && ps.sum(l, r - 1) <= c[r - 1])
                dp[l][r] = 1;
            if (dp[l + 1][r] == 1 && ps.sum(l + 1, r) <= c[l])
                dp[l][r] = 1;
        }
    }
    co(dp[0][n]);
    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 7296
final_rank: 4

code_snippet: // competitive-verifier: PROBLEM
#pragma GCC optimize("Ofast,fast-math,unroll-all-loops")
#include <bits/stdc++.h>
#if !defined(ATCODER) && !defined(EVAL)
#pragma GCC target("sse4.2,avx2,bmi2")
#endif
template <class T, class U>
constexpr bool chmax(T &a, const U &b) {
    return a < (T)b ? a = (T)b, true : false;
}
template <class T, class U>
constexpr bool chmin(T &a, const U &b) {
    return (T)b < a ? a = (T)b, true : false;
}
constexpr std::int64_t INF = 1000000000000000003;
constexpr int Inf = 1000000003;
constexpr double EPS = 1e-7;
constexpr double PI = 3.14159265358979323846;
#define FOR(i, m, n) for (int i = (m); i < int(n); ++i)
#define FORR(i, m, n) for (int i = (m) - 1; i >= int(n); --i)
#define FORL(i, m, n) for (std::int64_t i = (m); i < std::int64_t(n); ++i)
#define rep(i, n) FOR (i, 0, n)
#define repn(i, n) FOR (i, 1, n + 1)
#define repr(i, n) FORR (i, n, 0)
#define repnr(i, n) FORR (i, n + 1, 1)
#define all(s) (s).begin(), (s).end()
struct Sonic {
    Sonic() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        std::cout << std::fixed << std::setprecision(20);
    }
    constexpr void operator()() const {}
} sonic;
struct increment_impl {
    template <class T>
    const increment_impl &operator>>(std::vector<T> &v) const {
        for (auto &x : v) ++x;
        return *this;
    }
} Inc;
struct decrement_impl {
    template <class T>
    const decrement_impl &operator>>(std::vector<T> &v) const {
        for (auto &x : v) --x;
        return *this;
    }
} Dec;
struct sort_impl {
    template <class T>
    const sort_impl &operator>>(std::vector<T> &v) const {
        std::sort(v.begin(), v.end());
        return *this;
    }
} Sort;
struct unique_impl {
    template <class T>
    const unique_impl &operator>>(std::vector<T> &v) const {
        std::sort(v.begin(), v.end());
        v.erase(std::unique(v.begin(), v.end()), v.end());
        return *this;
    }
} Uniq;
using namespace std;
using ll = std::int64_t;
using ld = long double;
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
    return is >> p.first >> p.second;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
    for (T &i : v) is >> i;
    return is;
}
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
    return os << '(' << p.first << ',' << p.second << ')';
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &v) {
    for (auto it = v.begin(); it != v.end(); ++it) os << (it == v.begin() ? "" : " ") << *it;
    return os;
}
template <class Head, class... Tail>
void co(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cout << head << '\n';
    else std::cout << head << ' ', co(std::forward<Tail>(tail)...);
}
template <class Head, class... Tail>
void ce(Head &&head, Tail &&...tail) {
    if constexpr (sizeof...(tail) == 0) std::cerr << head << '\n';
    else std::cerr << head << ' ', ce(std::forward<Tail>(tail)...);
}
void Yes(bool is_correct = true) { std::cout << (is_correct ? "Yes\n" : "No\n"); }
void No(bool is_not_correct = true) { Yes(!is_not_correct); }
void YES(bool is_correct = true) { std::cout << (is_correct ? "YES\n" : "NO\n"); }
void NO(bool is_not_correct = true) { YES(!is_not_correct); }
void Takahashi(bool is_correct = true) { std::cout << (is_correct ? "Takahashi" : "Aoki") << '\n'; }
void Aoki(bool is_not_correct = true) { Takahashi(!is_not_correct); }
/// @brief 累積和
template <class T = std::int64_t>
struct prefix_sum {
    prefix_sum(int _n) : n(_n), data(_n + 1) {}
    template <class U>
    prefix_sum(const std::vector<U> &v) : n(v.size()), data(v.size() + 1) {
        for (int i = 0; i < n; ++i) data[i] = v[i];
        build();
    }
    void build() {
        for (int i = n - 1; i >= 0; --i) data[i] += data[i + 1];
    }
    T get(int k) const {
        assert(0 <= k && k < n);
        return data[k] - data[k + 1];
    }
    void set(int k, int x) { data[k] = x; }
    void add(int k, int x) { data[k] += x; }
    T sum(int r) const {
        assert(0 <= r && r <= n);
        return data[0] - data[r];
    }
    T sum(int l, int r) const {
        assert(0 <= l && l <= r && r <= n);
        return data[l] - data[r];
    }
    int min_left(T x) const { return min_left(0, x); }
    int min_left(int l, T x) const {
        assert(0 <= l && l <= n);
        int left = l, right = n + 1;
        while (right - left > 1) {
            int mid = (left + right) / 2;
            (data[l] - data[mid] >= x ? right : left) = mid;
        }
        return right;
    }
    int max_right(T x) const { return max_right(n, x); }
    int max_right(int r, T x) const {
        assert(0 <= r && r <= n);
        int left = -1, right = r;
        while (right - left > 1) {
            int mid = (left + right) / 2;
            (data[mid] - data[r] >= x ? left : right) = mid;
        }
        return left;
    }
  private:
    int n;
    std::vector<T> data;
};
int main(void) {
    int n;
    cin >> n;
    vector<int> c(n), w(n);
    rep (i, n) cin >> c[i] >> w[i];
    rep (i, n) {
        c.emplace_back(c[i]);
        w.emplace_back(w[i]);
    }
    prefix_sum<ll> ps(w);
    vector dp(n * 2 + 1, vector(n * 2 + 1, 0));
    rep (i, n * 2) dp[i][i + 1] = 1;
    FOR (d, 2, n + 1) {
        rep (l, n * 2) {
            int r = l + d;
            if (r > n * 2)
                break;
            dp[l][r] = r - l;
            FOR (m, l + 1, r) chmin(dp[l][r], dp[l][m] + dp[m][r]);
            if (dp[l][r - 1] == 1 && ps.sum(l, r - 1) <= c[r - 1])
                dp[l][r] = 1;
            if (dp[l + 1][r] == 1 && ps.sum(l + 1, r) <= c[l])
                dp[l][r] = 1;
        }
    }
    co(dp[0][n]);
    return 0;
}
accuracy: 1
time_ms: 430
memory_kb: 19072
final_rank: 20

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<pair<int,int>> a(n);
	vector<int> s(n,0);
	for(int i = 0;i < n;i++){
		cin >> a[i].first >> a[i].second;
		s[i] += a[i].second;
		if(i != 0){
			s[i] += s[i - 1];
		}
	}
	function<int(int,int)> sum = [&](int l,int r) -> int {
		return s[r] - (l == 0 ? 0 : s[l - 1]);
	};
	vector<vector<int>> dp(n,vector<int>(n,INT_MAX));
	for(int i = 0;i < n;i++){
		dp[i][i] = 1;
	}
	for(int i = 2;i <= n;i++){
		for(int j = 0;j < n;j++){
			int r = j + i - 1;
			if(r >= n) break;
			if(sum(j + 1,r) <= a[j].first && dp[j + 1][r] == 1){
				dp[j][r] = min(dp[j][r],dp[j][j]);
			}
			if(sum(j,r - 1) <= a[r].first && dp[j][r - 1] == 1){
				dp[j][r] = min(dp[j][r],dp[r][r]);
			}
			for(int k = j;k < r;k++){
				dp[j][r] = min(dp[j][r],dp[j][k] + dp[k + 1][r]);
			}
		}
	}
	cout << dp[0][n - 1] << endl;
}
accuracy: 1
time_ms: 140
memory_kb: 7364
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int n;
	cin >> n;
	vector<pair<int,int>> a(n,pair<int,int>());
	for(int i = 0;i < n;i++){
		cin >> a[i].first >> a[i].second;
	}
	vector<vector<int>> dp(n,vector<int>(n,n));
	for(int i = 0;i < n;i++) dp[i][i] = 1;
	vector<int> sum(n);
	sum[0] = a[0].second;
	for(int i = 1;i < n;i++){
		sum[i] = sum[i - 1] + a[i].second;
	}
	for(int d = 1;d < n;d++){
		for(int i = 0;i < n;i++){
			int left = i,right = i + d;
			if(right >= n) continue;
			if(dp[left + 1][right] == 1){
				int it = sum[right];
				it -= sum[left];
				if(it <= a[left].first){
					dp[left][right] = 1;
				}else{
					dp[left][right] = min(dp[left][right],2);
				}
			}
			if(dp[left][right - 1] == 1){
				int it = sum[right - 1];
				if(left != 0){
					it -= sum[left - 1];
				}
				if(it <= a[right].first){
					dp[left][right] = 1;
				}else{
					dp[left][right] = min(dp[left][right],2);
				}
			}
			for(int k = left;k < right;k++){
				dp[left][right] = min(dp[left][right],dp[left][k] + dp[k + 1][right]);
			}
		}
	}
	cout << dp[0][n - 1] << endl;
}
accuracy: 1
time_ms: 130
memory_kb: 7396
final_rank: 5

code_snippet: #include <iostream>
#include <utility>
#include <vector>
#include <string>
#include <cmath>
#include <algorithm>
#include <functional>
#include <iomanip>
#include <map>
#include <set>
#include <queue>
using namespace std;
using ll = long long int;
#define chmax(x,y)  (x) = ((x) > (y)) ? (x) : ((x) = (y));
#define chmin(x,y)  (x) = ((x) < (y)) ? (x) : ((x) = (y));
const int INF = 1e9;

int main(int argc, char const *argv[])
{
  int N; cin >> N;
  vector<pair<int,int>> data(N);
  for(auto &d : data) cin >> d.first >> d.second;
  vector<int> sumw(N+1);
  for(int i=0;i<N;++i)
  {
    sumw[i+1] = sumw[i] + data[i].second;
  }
  vector<vector<int>> dp(N+1,vector<int>(N+1,INF));
  vector<vector<int>> weight(N+1,vector<int>(N+1));
  for(int i=0;i<N;++i)
  {
    dp[i][i+1] = 1;
  }

  for(int len=2;len<=N;++len)
  {
    for(int i=0;i<N;++i)
    {
      int r = i+len;
      if(r > N)continue;
      for(int k=i+1;k<r;++k)
      {
        chmin(dp[i][r],dp[i][k]+dp[k][r]);
      }
      int lcap = data[i].first;
      int rcap = data[i+len-1].first;
      if( dp[i+1][i+len] == 1  && lcap >= sumw[i+len] - sumw[i+1])
      {
        chmin(dp[i][r],1);
      }
      if(dp[i][i+len-1] == 1 && rcap >= sumw[i+len-1] - sumw[i])
      {
        chmin(dp[i][r],1);
      }
    }
  }

  std::cout << dp[0][N] << std::endl;
}
accuracy: 1
time_ms: 140
memory_kb: 11248
final_rank: 13

code_snippet: #include<iostream>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<set>
#include<string>
#include<map>
#include<string.h>
#include<complex>
#include<math.h>
#include<queue>
#include <functional>
#include<time.h>
#include<iomanip>
#include<cassert>
#include<bitset>
#include<sstream>
#include <unordered_set>
using namespace std;
typedef long long int llint;
typedef pair<int, int> pint;
typedef pair<llint, llint> pllint;
typedef vector<int> vint;
typedef vector<llint> vllint;
typedef vector<pint> vpint;
typedef vector<string> vstring;
typedef vector<pair<llint, llint>> vpllint;
typedef vector<vector<int>> vvint;
typedef vector<vector<llint>> vvllint;
typedef vector<vector<pint>> vvpint;
typedef vector<bool> vbool;
typedef vector<vbool> vvbool;
typedef vector<vpllint> vvpllint;
#define rep(i,n) for(int i=0;i<n;i++)
#define drep(i,n) for(int i=n-1;0<=i;i--)
#define yes(ans) if(ans)cout<<"yes"<<endl;else cout<<"no"<<endl;
#define Yes(ans) if(ans)cout<<"Yes"<<endl;else cout<<"No"<<endl;
#define YES(ans) if(ans)cout<<"YES"<<endl;else cout<<"NO"<<endl;
#define POSSIBLE(ans) if(ans)cout<<"POSSIBLE"<<endl;else cout<<"IMPOSSIBLE"<<endl;
#define Pi 3.1415926535897932384626
#define mod llint(1e9+7)
#define mod9 998244353
#define Inf 2147483647
#define llInf 9223372036854775807
#define all(x) x.begin(),x.end()
#define isin(i,n) (0<=i&&i<n)

class UnionFind {
public:
	//親の番号を格納する。親だった場合は-(その集合のサイズ)
	vector<int> Parent;

	//作るときはParentの値を全て-1にする
	//こうすると全てバラバラになる
	UnionFind(int N) {
		Parent = vector<int>(N, -1);
	}

	//Aがどのグループに属しているか調べる
	int root(int A) {
		if (Parent[A] < 0) return A;
		return Parent[A] = root(Parent[A]);
	}

	//自分のいるグループの頂点数を調べる
	int size(int A) {
		return -Parent[root(A)];//親をとってきたい
	}

	//AとBをくっ付ける
	bool connect(int A, int B) {
		//AとBを直接つなぐのではなく、root(A)にroot(B)をくっつける
		A = root(A);
		B = root(B);
		if (A == B) {
			//すでにくっついてるからくっ付けない
			return false;
		}

		//大きい方(A)に小さいほう(B)をくっ付けたい
		//大小が逆だったらひっくり返しちゃう。
		if (size(A) < size(B)) swap(A, B);

		//Aのサイズを更新する
		Parent[A] += Parent[B];
		//Bの親をAに変更する
		Parent[B] = A;

		return true;
	}
};

//セグ木・0-indexed・非再帰・(大きさ・単位元・関数)で初期化
template<typename T>
struct SegTree {
	//比較関数の型
	using F = function<T(T, T)>;
	//二分木を配列で表したもの
	vector<T>seg;
	//木の半分の大きさ
	int siz;
	//単位元
	const T unit;
	//比較する関数
	const F f;

	//大きさn、unit(単位元)、f(モノイド)でsegtreeを初期化する
	SegTree(int n, const T unit, const F f) : unit(unit), f(f) {
		siz = 1;
		while (siz < n)siz <<= 1;
		seg.assign(siz * 2 - 1, unit);
		siz--;
	}

	//k番目にtを入力
	void set(int k, const T& t) {
		seg[k + siz] = t;
	}

	//fによって木を構築する
	void build() {
		for (int i = siz - 1; 0 <= i; i--) {
			seg[i] = f(seg[i * 2 + 1], seg[i * 2 + 2]);
		}
	}

	T operator[](const int i) {
		return seg[i + siz];
	}

	//k番目をxに更新する
	void update(int k, T x) {
		k += siz;
		seg[k] = x;
		while (0 < k) {
			k = (k - 1) >> 1;
			seg[k] = f(seg[k * 2 + 1], seg[k * 2 + 2]);
		}
	}

	//[a,b)について、fした結果を返す
	//半開区域のためa以上b未満の位置を指す
	T query(int a, int b) {
		T l = unit, r = unit;
		for (a += siz, b += siz; a < b; a >>= 1, b >>= 1) {
			if (!(a & 1))l = f(l, seg[a++]);
			if (!(b & 1))r = f(seg[--b], r);
		}
		return f(l, r);
	}
};

//aとbの最大公約数を求めるよ
long long GCD(long long a, long long b) {
	if (b == 0) return a;
	else return GCD(b, a % b);
}

// 返り値: a と b の最大公約数
// ax + by = gcd(a, b) を満たす (x, y) が格納される
long long extGCD(long long a, long long b, long long& x, long long& y) {
	if (b == 0) {
		x = 1;
		y = 0;
		return a;
	}
	long long d = extGCD(b, a % b, y, x);
	y -= a / b * x;
	return d;
}

// mod. m での a の逆元 a^{-1} を計算する
long long modinv(long long a, long long m) {
	long long b = m, u = 1, v = 0;
	while (b) {
		long long t = a / b;
		a -= t * b; swap(a, b);
		u -= t * v; swap(u, v);
	}
	u %= m;
	if (u < 0) u += m;
	return u;
}

//nCrをmで割った余りを求める
llint nCr(llint n, llint r, llint m) {
	llint ans = 1;
	for (llint i = 0; i < r; i++) {
		ans *= n - i;
		ans %= m;
	}
	for (llint i = 1; i <= r; i++) {
		ans *= modinv(i, m);
		ans %= m;
	}
	return ans;
}

//aのb乗をmで割った余りを求める
llint power(llint a, llint b, llint m) {
	if (b == 1)return a;
	if (b == 0)return 1;
	llint tmp = power(a, (llint)b / 2, m);
	tmp *= tmp;
	tmp %= m;
	if (b % 2 == 1) {
		tmp *= a;
		tmp %= m;
	}
	return tmp;
}

//bitを表すsub,要素数を表すlength
bool next_combination(llint& sub, int length) {
	llint x = sub & -sub, y = sub + x;
	sub = (((sub & ~y) / x) >> 1) | y;
	return sub < (llint)(1 << (llint)length);
}

void Zalgorithm(string& s, vint& a) {
	a[0] = s.size();
	int i = 1, j = 0;
	while (i < s.size()) {
		while (i + j < s.size() && s[j] == s[i + j])j++;
		a[i] = j;
		if (j == 0) { i++; continue; }
		int k = 1;
		while (i + k < s.size() && a[k] + k < j) {
			a[i + k] += a[k]; k++;
		}
		i += k; j -= k;
	}
	return;
}

struct maccho {
	int c;
	int w;
};

int main() {
	int n;
	cin >> n;
	vector<maccho>macchos(n);
	for (auto& [c, w] : macchos) {
		cin >> c >> w;
	}
	vint cs(n + 1);
	rep(i, n) {
		cs[i + 1] = cs[i] + macchos[i].w;
	}
	rep(i, n)macchos[i].c += macchos[i].w;
	//区間DP
	//dp[l][r]={半開区間[l,r)内での最小人数、一番下のマッチョの番号}
	vvpint dp(n, vpint(n + 1));
	rep(i, n)rep(j, n + 1) {
		dp[i][j].first = Inf; dp[i][j].second = -1;
	}
	rep(d, n + 1) {
		if (d == 0)continue;
		rep(l, n - d + 1) {
			int r = l + d;
			if (d == 1) {
				dp[l][r].first = 1;
				dp[l][r].second = l;
			}
			else {
				for (int k = l + 1; k < r; k++) {
					if (dp[l][r].first > dp[l][k].first + dp[k][r].first) {
						dp[l][r].first = dp[l][k].first + dp[k][r].first;
						dp[l][r].second = -1;
					}
					if (dp[l][k].first != 1 || dp[k][r].first != 1) {
						continue;
					}
					if (k == l + 1 && macchos[dp[l][k].second].c >= cs[r] - cs[l] &&
						(dp[l][r].second == -1 ||
							dp[l][r].second != -1 && macchos[dp[l][k].second].c > macchos[dp[l][r].second].c)) {
						dp[l][r].first = 1;
						dp[l][r].second = dp[l][k].second;
					}
					if (k == r - 1 && macchos[dp[k][r].second].c >= cs[r] - cs[l] &&
						(dp[l][r].second == -1 ||
							dp[l][r].second != -1 && macchos[dp[k][r].second].c > macchos[dp[l][r].second].c)) {
						dp[l][r].first = 1;
						dp[l][r].second = dp[k][r].second;
					}
				}
			}
		}
	}
	cout << dp[0][n].first << endl;
	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 11032
final_rank: 14

code_snippet: #include <stdio.h>
int min(int a,int b){return a>b?b:a;}
struct man{
    int pow;
    int wei;
    void in(){
        scanf("%d%d",&pow,&wei);
        return ;
    }
    void operator =(man a){
        pow=a.pow;
        wei=a.wei;
        return ;
    }
    man carry(man a){
        pow-=a.wei;
        wei+=a.wei;
        pow=min(pow,a.pow);
        return *this;
    }
    void bebad(){
        pow=-2;
        return ;
    }
    bool isbad(){
        return pow==-2;
    }
};
bool can(man a,man b){
    return a.pow>=b.wei;
}
man max(man a,man b){
    return a.pow>b.pow?a:b;
}
int max(int a,int b){return a>b?a:b;}
bool better(man a,man b){
    return a.pow>b.pow;
}
const int N=1e3+10;
int main(){
    int n,val[N][N],h[N][N];
    man a[N][N],l,r;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        a[i][i].in();
        h[i][i]=i;
        val[i][i]=1;
    }
    for(int j=1;j<n;j++){
        l=a[j][j];
        r=a[j+1][j+1];
        h[j][j+1]=j;
        
        if(can(l,r)){
            if(can(r,l))a[j][j+1]=max(l.carry(a[j+1][j+1]),r.carry(a[j][j]));
            else a[j][j+1]=l.carry(r);
            val[j][j+1]=1;
        }
        else if(can(r,l)){
            a[j][j+1]=r.carry(l);
            val[j][j+1]=1;
        }
        else{
            val[j][j+1]=2;
            a[j][j+1].bebad();
        }
    }
    for(int i=2;i<n;i++){
        for(int j=1;j<=n-i;j++){
            h[j][j+i]=h[j][j+i-1];
            l=a[j][j];
            r=a[j+1][j+i];
            val[j][j+i]=i+1;
            if(r.isbad()){
                val[j][j+i]=val[j][j]+val[j+1][j+i];
                a[j][j+i].bebad();
            }
            else{
                if(can(l,r)){
                    a[j][j+i]=l.carry(r);
                    val[j][j+i]=1;
                }
                else{
                    val[j][j+i]=2;
                    a[j][j+i].bebad();
                }
            }
            l=a[j][j+i-1];
            r=a[j+i][j+i];
            if(l.isbad()){
                if(val[j][j+i]>val[j][j+i-1]+val[j+i][j+i]){
                    val[j][j+i]=val[j][j+i-1]+val[j+i][j+i];
                    a[j][j+i].bebad();
                }
            }
            else{
                if(can(r,l)){
                    if(val[j][j+i]>1){
                        val[j][j+i]=1;
                        h[j][j+i]=j+i-1;
                        a[j][j+i]=r.carry(l);
                    }
                    else if(val[j][j+i]==1&&better(r.carry(l),a[j][j+i])){
                            h[j][j+i]=j+i-1;
                            a[j][j+i]=r;
                    }
                    
                }
                else{
                    if(val[j][j+i]>2){
                        val[j][j+i]=2;
                        h[j][j+i]=j+i-1;
                        a[j][j+i].bebad();
                    }
                }
                
            }
            for(int k=max(h[j][j+i-1]-10,j);k<=h[j+1][j+i]&&k<j+i;k++){
                if(val[j][k]+val[k+1][j+i]<val[j][j+i]){
                    val[j][j+i]=val[j][k]+val[k+1][j+i];
                    a[j][j+i].bebad();
                    h[j][j+i]=k;
                }
            }
            //printf("val[%d][%d]=%d\n",j,j+i,val[j][j+i]);
        }
    }
    //for(int i=1;i<=n;i++)for(int j=i;j<=n;j++)printf("val[%d][%d]=%d\n",i,j,val[i][j]);
    printf("%d\n",val[1][n]);
}
/*val[1][1]=0
val[1][2]=1
val[1][3]=1
val[1][4]=2
val[1][5]=2
val[1][6]=2
val[1][7]=3
val[2][2]=0
val[2][3]=1
val[2][4]=2
val[2][5]=2
val[2][6]=2
val[2][7]=3
val[3][3]=1
val[3][4]=1
val[3][5]=1
val[3][6]=1
val[3][7]=2
val[4][4]=1
val[4][5]=1
val[4][6]=1
val[4][7]=2
val[5][5]=1
val[5][6]=1
val[5][7]=1
val[6][6]=1
val[6][7]=1
val[7][7]=1*/
accuracy: 1
time_ms: 10
memory_kb: 17572
final_rank: 17

code_snippet: #include "bits/stdc++.h"
#define REP(i,n,N) for(int i=(n); i<(N); i++)
#define RREP(i,n,N) for(ll i=(N-1); i>=n; i--)
#define CK(n,a,b) ((a)<=(n)&&(n)<(b))
#define ALL(v) (v).begin(),(v).end()
#define p(s) cout<<(s)<<endl
#define p2(a,b) cout<<(a)<<" "<<(b)<<endl
#define v2(T) vector<vector<T>>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int inf=1e9;

int dp[1010][1010];
int N;
int C[1010], W[1010];
int sum[1010];
int main() {
    cin>>N;
    REP(i,0,N){
        cin>>C[i]>>W[i];
    }
    REP(i,0,N) REP(j,i,N) dp[i][j] = j-i+1;
    REP(i,0,N) sum[i+1] = sum[i] + W[i];
    REP(k,1,N){
        REP(L,0,N-k){
            int R = L + k;
            if(dp[L+1][R]==1 && sum[R+1]-sum[L+1] <= C[L]){
                dp[L][R] = min(dp[L][R], dp[L+1][R]);
            }
            if(dp[L][R-1]==1 && sum[R]-sum[L] <= C[R]){
                dp[L][R] = min(dp[L][R], dp[L][R-1]);
            }
            REP(i,L,R) {
                dp[L][R] = min(dp[L][R], dp[L][i] + dp[i+1][R]);
            }
        }
    }
    p(dp[0][N-1]);

    return 0;
}
accuracy: 1
time_ms: 240
memory_kb: 7064
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <utility>
#include <string>
#include <stack>
#include <regex>

#define REP(i, n) for (int i = 0; i < n; i++)
#define ALL(v) (v).begin(), (v).end()
#define vi vector<int>
#define vvi vector<vector<int>>
#define INF 1e9

using namespace std;

typedef long long ll;

int main()
{
  int n;
  cin >> n;

  vi w = vi(n, 0);
  vi csum = vi(n, 0);
  vi c = vi(n, 0);
  REP(i, n)
  {
    cin >> c[i] >> w[i];
  }
  vvi dp = vvi(n, vi(n, INF));
  REP(i, n)
  {
    dp[i][i] = 1;
  }
  csum[0] = w[0];
  for (int i = 1; i < n; i++)
  {
    csum[i] = csum[i - 1] + w[i];
  }
  for (int count = 2; count <= n; count++)
  {
    REP(left, n)
    {
      int right = left + count - 1;
      if (right >= n)
      {
        continue;
      }

      // 一番下が一人になる時
      if (csum[right] - csum[left] <= c[left] && dp[left + 1][right] == 1)
        dp[left][right] = 1;
      if (csum[right - 1] - csum[left - 1] <= c[right] && dp[left][right - 1] == 1)
        dp[left][right] = 1;

      // min
      for (int k = left; k < right; k++)
      {
        dp[left][right] = min(dp[left][right], dp[left][k] + dp[k + 1][right]);
      }
    }
  }
  cout << dp[0][n - 1] << endl;
  return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 6832
final_rank: 7

code_snippet: #include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
#define pb push_back
int dy[]={0, 0, 1, -1, 1, 1, -1, -1};
int dx[]={1, -1, 0, 0, 1, -1, -1, 1};

#define FOR(i,a,b) for (int i=(a);i<(b);i++)
#define RFOR(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define REP(i,n) for (int i=0;i<(n);i++)
#define RREP(i,n) for (int i=(n)-1;i>=0;i--)
#define mp make_pair
#define fi first
#define sc second
ll n,c[2000],w[2000],a[2000];
ll W(ll i,ll j) {
	return a[j + 1] - a[i];
}
ll memo[2000][2000];

ll solve(ll i,ll j) {
	if(memo[i][j] >= 0) {
		return memo[i][j];
	}
	if(j - i + 1 <= 2) {
		if(i == j || w[i] <= c[j] || w[j] <= c[i]) {
			return memo[i][j] = 1;
		}
		return memo[i][j] = 2;
	}


	ll ret = 1000000000;

	if((solve(i + 1,j) == 1 && c[i] >= W(i + 1,j)) || (solve(i,j - 1) == 1 && c[j] >= W(i,j - 1))) {
		ret = 1;
	} 
	REP(k,j - i) {
		ret = min(ret,solve(i,i + k) + solve(i + k + 1,j));
	}
	return memo[i][j] = ret;
}

int main(){
	cin >> n;
	REP(i,n) {
		cin >> c[i] >> w[i];
	}
	REP(i,n) {
		REP(j,n) {
			memo[i][j] = -1;
		}
	}

	a[0] = 0;
	REP(i,n) {
		a[i + 1] = a[i] + w[i];
	}

	cout << solve(0,n - 1) << endl;
	return 0;
}
accuracy: 1
time_ms: 420
memory_kb: 14936
final_rank: 19

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
#include <string.h>
#include <cmath>

using namespace std;
typedef long long i64;
typedef long double ld;
typedef pair<i64,i64> P;
#define rep(i,s,e) for(int (i) = (s);(i) <= (e);++(i))

int n;

i64 c[1010];
i64 w[1010];

i64 sum[1010];

int dp[1010][1010];

int main()
{
	cin >> n;
	rep(i,0,n - 1)
		cin >> c[i] >> w[i];

	rep(i,1,n)
	{
		sum[i] = sum[i - 1] + w[i - 1];
	}

	auto getsum = [&](int l,int r){
		return sum[r] - sum[l];
	};

	rep(i,0,1000) rep(j,0,1000) dp[i][j] = 1e9;

	rep(i,0,1000)
		dp[i][i + 1] = 1;
	
	rep(w,2,n)
	{
		rep(l,0,n - 1)
		{
			//[l,r)
			int r = l + w;
			if(r > n) continue;

			rep(mid,l + 1,r - 1)
			{
				dp[l][r] = min(dp[l][r] , dp[l][mid] + dp[mid][r]);
			}

			//left is mighty
			{

				i64 w_s = getsum(l + 1,r);
				if(c[l] >= w_s && dp[l + 1][r] == 1)
				{
					dp[l][r] = 1;
				}
			}
			{
				i64 w_s = getsum(l,r - 1);
				if(c[r - 1] >= w_s && dp[l][r - 1] == 1)
				{
					dp[l][r] = 1;
				}
			}
			/*
			rep(i,0,n)
			{
				if(l <= i && i < r)
					cout << "=";
				else
					cout << " ";
			}
			cout << dp[l][r] << endl;
			*/
		}

	}

	cout << dp[0][n] << endl;

}
accuracy: 1
time_ms: 230
memory_kb: 7108
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#define REP(i, a, n) for(ll i = ((ll) a); i < ((ll) n); i++)
#define INF (1LL << 60)
using namespace std;
typedef long long ll;

ll N, C[2000], W[2000];
ll sum[2000], memo[2000][2000];

struct edge {
  ll v, dist;
};

struct state {
  ll v, cost;

  bool operator>(const state s) const {
    return cost > s.cost;
  }
};

vector<ll> dijkstra(vector< vector<edge> > &E, ll S) {
  vector<ll> dp(E.size(), INF);
  priority_queue<state, vector<state>, greater<state> > q;
  q.push((state) { S, 0 });

  while(!q.empty()) {
    ll v = q.top().v, cost = q.top().cost;
    q.pop();

    if(dp[v] <= cost) continue;
    dp[v] = cost;

    REP(i, 0, E[v].size()) {
      ll nv = E[v][i].v, ncost = cost + E[v][i].dist;
      if(dp[nv] > ncost) q.push((state) { nv, ncost });
    }
  }

  return dp;
}

ll dfs(ll l, ll r) {
  ll &ret = memo[l][r];
  if(ret >= 0) return ret;

  if(r - l <= 1) return ret = 1;

  ret = 0;
  if(dfs(l + 1, r) && (sum[r] - sum[l + 1] <= C[l])) ret = 1;
  if(dfs(l, r - 1) && (sum[r - 1] - sum[l] <= C[r - 1])) ret = 1;
  return ret;
}

int main(void) {
  cin >> N;
  REP(i, 0, N) cin >> C[i] >> W[i];

  sum[0] = 0;
  REP(i, 0, N) sum[i + 1] = sum[i] + W[i];

  REP(i, 0, N) REP(j, 0, N + 1) memo[i][j] = -1;

  vector< vector<edge> > E(N + 1);
  REP(i, 0, N) REP(j, i, N + 1) if(dfs(i, j)) E[i].push_back((edge) { j, 1 });
  cout << dijkstra(E, 0)[N] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 17544
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;


int c[1010];
int w[1010];
int sum[1010];
int dp[1010][1010];

int f(int l, int r){
	if(dp[l][r] != -1) return dp[l][r];
	int len = r - l;
	if(len == 1) return dp[l][r] = 1;

	int ok = 0;
	if(c[l] >= sum[r] - sum[l + 1] && f(l + 1, r)) ok = 1;
	if(c[r - 1] >= sum[r - 1] - sum[l] && f(l, r - 1)) ok = 1;
	return dp[l][r] = ok;
}

int dp2[1010];

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
#ifdef LOCAL
	std::ifstream in("in");
	std::cin.rdbuf(in.rdbuf());
#endif

	int n;
	cin >> n;
	for(int i = 0; i < n; i++){
		cin >> c[i] >> w[i];
		sum[i + 1] = sum[i] + w[i];
	}

	memset(dp, -1, sizeof dp);
	fill((int*)begin(dp2), (int*)end(dp2), 1 << 25);
	dp2[0] = 0;
	for(int i = 0; i < n; i++){
		for(int j = i + 1; j <= n; j++){
			if(f(i, j)){
				dp2[j] = min(dp2[j], dp2[i] + 1);
			}
		}
	}

	cout << dp2[n] << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 7200
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define FOR(i,a,b) for(int i=(a);i<(b);i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
#define fi first
#define se second

template<typename A, typename B> inline bool chmax(A &a, B b) { if (a<b) { a=b; return 1; } return 0; }
template<typename A, typename B> inline bool chmin(A &a, B b) { if (a>b) { a=b; return 1; } return 0; }

typedef long long ll;
typedef pair<int, int> pii;

const ll INF = 1ll<<29;
const ll MOD = 1000000007;
const bool debug = 0;

int N;
bool dp1[1000][1001]; // [l,r)???1???????????¨???????????¨?????§??????
int dp2[1001]; // i????????§???????????????????°??????°
int c[1000], w[1000];
int sum[1001];

int main() {
	cin >> N;
	REP(i, N) scanf("%d %d", c + i, w + i);
	
	REP(i, N) sum[i + 1] = sum[i] + w[i];
	
	REP(i, N) dp1[i][i + 1] = true;
	FOR(w, 2, N + 1) {
		REP(i, N) {	// [i, i + w)
			if (i + w > N) break;
			
			if (dp1[i + 1][i + w] && sum[i + w] - sum[i + 1] <= c[i])
				dp1[i][i + w] = true;
			if (dp1[i][i + w - 1] && sum[i + w - 1] - sum[i] <= c[i + w - 1])
				dp1[i][i + w] = true;
		}
	}
	
	fill(dp2, dp2 + N + 1, INF);
	
	dp2[0] = 1;
	REP(i, N) {
		FOR(j, i + 1, N + 1) {
			if (dp1[i][j]) {
				if (i == 0) dp2[j] = 1;
				else chmin(dp2[j], dp2[i] + 1);
			}
		}
	}
	
	cout << dp2[N] << endl;
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4240
final_rank: 1

code_snippet: #include <iostream>
#define INF 1e+9
using namespace std;

int n,w[1000],c[1000],imos[1001] = {};
bool dp1[1000][1000];
int dp2[1000][1000];

int dfs(int l,int r){
	if(dp2[l][r] >= 0) return dp2[l][r];
	int mi = INF;
	for(int i = l;i < r;i++) mi = min(mi,dfs(l,i) + dfs(i + 1,r));
	return dp2[l][r] = mi;
}

int main(){
	cin >> n;
	for(int i = 0;i < n;i++){
		cin >> c[i] >> w[i];
		imos[i + 1] = imos[i] + w[i];
		dp1[i][i] = true;
		for(int j = 0;j < n;j++) dp2[i][j] = -1;
		dp2[i][i] = 1;
	}
	for(int i = 1;i < n;i++){
		for(int j = 0;j < n - i;j++){
			if((c[j + i] >= imos[j + i] - imos[j] && dp1[j][j + i - 1]) || (c[j] >= imos[j + i + 1] - imos[j + 1] && dp1[j + 1][j + i])) dp1[j][j + i] = true;
			else dp1[j][i + j] = false;
			if(dp1[j][i + j]) dp2[j][i + j] = 1;
		}
	}
	cout << dfs(0,n - 1) << endl;
	return 0;
}
accuracy: 1
time_ms: 400
memory_kb: 8056
final_rank: 15

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
typedef long long int ll;
#define BIG_NUM 2000000000
#define MOD 1000000007
using namespace std;

 int main(){

	 int N;
	 scanf("%d",&N);

	 int* power = new int[N+1];
	 int* weight = new int[N+1];
	 bool** table = new bool*[N+1];
	 int** dp = new int*[N+1];
	 for(int i = 0; i <= N; i++){
		 table[i] = new bool[N+1];
		 dp[i] = new int[N+1];
		 for(int k = 0; k <= N; k++){
			 table[i][k] = false;
			 dp[i][k] = BIG_NUM;
		 }
	 }

	 for(int i = 1; i <= N; i++){
		 scanf("%d %d",&power[i],&weight[i]);
     }

	 weight[0] = 0;
	 for(int i = 1; i <= N; i++){
		 weight[i] += weight[i-1];
		 table[i][1] = true;
		 dp[i][i] = 1;
	 }

	 for(int length=2; length <= N; length++){
		  for(int left = 1; left + length -1 <= N;left++){
			  if((power[left] >= (weight[left+length-1]-weight[left]) && table[left+1][length-1]  == true) ||
					 (power[left+length-1] >= (weight[left+length-2]-weight[left-1]) && table[left][length-1]) == true){
				table[left][length] = true;
				dp[left][left+length-1] = 1;
			 }else{
				  for(int i = left; i <= left+length-2; i++){
					 dp[left][left+length-1] = min(dp[left][left+length-1],dp[left][i]+dp[i+1][left+length-1]);
				 }
			 }
		 }
	 }

	 printf("%d\n",dp[1][N]);

	return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 7692
final_rank: 11

code_snippet: #include <bits/stdc++.h>
#define REP(i,n,N) for(int i=n;i<N;i++)
#define p(S) cout<<(S)<<endl
using namespace std;
int dp[1001][1001];
int w[1001],c[1001];
int sumw[1001];
int main(){
	int n;
	cin>>n;
	cin>>c[0]>>w[0];
	sumw[0]=w[0];
	REP(i,1,n) {
		cin>>c[i]>>w[i];
		sumw[i]=sumw[i-1]+w[i];
	}
	REP(i,0,n) REP(j,i,n) dp[i][j]=j-i+1;
	REP(i,0,n-1)  if(c[i]>=w[i+1]||c[i+1]>=w[i]) dp[i][i+1]=1;

	for(int k=2;k<n;k++){
		for(int i=0;i+k<n;i++){
			if((dp[i+1][i+k]==1&&c[i]>=sumw[i+k]-sumw[i])||(dp[i][i+k-1]==1&&c[i+k]>=sumw[i+k-1]-(i?sumw[i-1]:0)))
				dp[i][i+k]=1;
			for(int j=i+1;j<i+k;j++)
				dp[i][i+k]=min(dp[i][i+k],dp[i][j]+dp[j+1][i+k]);
		}
	}
	p(dp[0][n-1]);
	return 0;
}
accuracy: 1
time_ms: 250
memory_kb: 6996
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#define REP(i,n,N) for(int i=n;i<N;i++)
#define p(S) cout<<(S)<<endl
using namespace std;
int dp[1001][1001];
int w[100010],c[100010];
int sumw[100010];
int main(){
	int n;
	cin>>n;
	REP(i,0,n) {
		cin>>c[i]>>w[i];
		if(i>0)	sumw[i]=sumw[i-1]+w[i];
		else sumw[i]=w[i];
	}
	REP(i,0,1001) REP(j,i,1001) dp[i][j]=j-i+1;
	REP(i,0,n-1)  if(c[i]>=w[i+1]||c[i+1]>=w[i]) dp[i][i+1]=1;


	for(int k=2;k<n;k++){
		for(int i=0;i+k<n;i++){
			if((dp[i+1][i+k]==1&&c[i]>=sumw[i+k]-sumw[i])||(dp[i][i+k-1]==1&&c[i+k]>=sumw[i+k-1]-(i?sumw[i-1]:0)))
				dp[i][i+k]=1;
			else dp[i][i+k]=min(dp[i+1][i+k],dp[i][i+k-1])+1;

			for(int j=i+1;j<i+k;j++)
				dp[i][i+k]=min(dp[i][i+k],dp[i][j]+dp[j+1][i+k]);
		}
	}
	p(dp[0][n-1]);
	return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 7000
final_rank: 12

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;

//// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt"

int memo[2010][2010];
vector<int>sums, cs, aws;
int getnum(int l, int r) {
	if (memo[l][r])return memo[l][r];
	else {
		if (l + 1 == r)return 1;
		else {
			int amin = r-l;
			for (int m = l + 1; m <= r - 1; ++m) {
				const int lnum = getnum(l, m);
				const int rnum = getnum(m, r);
				if (m == l + 1) {
					if (rnum == 1) {
						if (sums[r-1] - sums[m - 1] <= cs[l]) {
							amin = 1;
						}
					}
				}
				if (m == r - 1) {
					if (lnum == 1) {
						if (sums[m - 1] - sums[l - 1] <= cs[r-1]) {
							amin = 1;
						}
					}
				}
				amin = min(amin, lnum + rnum);
			}
			return memo[l][r]=amin;
		}
	}
}

int main() {
	int N; 
	cin >> N;
	aws.resize(N+1);
	sums.resize(N + 1);
	cs.resize(N+1);
	for (int i = 0; i < N; ++i) {
		cin >> cs[i + 1];
		cin >> aws[i + 1];
		sums[i + 1] = sums[i] + aws[i + 1];
	}
	int ans = getnum(1, N + 1);
	cout << ans << endl;

	return 0;
}
accuracy: 1
time_ms: 620
memory_kb: 9144
final_rank: 18

code_snippet: #include <cstdio>
#include <algorithm>

#define rep(i, n) for(int i = 0; i < (n); ++i)

using namespace std;

const int inf = 3e5;

int n;
int c[1000];
int w[1000];
int dp[1000][1000];

int judge(int x, int y){
	if(dp[x][y] > 0){
		return dp[x][y];
	}
	if(x == y){
		return dp[x][y] = w[x];
	}
	int t;
	if((t = judge(x + 1, y)) <= c[x]){
		return dp[x][y] = t + w[x];
	}
	if((t = judge(x, y - 1)) <= c[y]){
		return dp[x][y] = t + w[y];
	}
	return dp[x][y] = inf;
}

int main(){
	scanf("%d", &n);
	rep(i, n){
		scanf("%d%d", &c[i], &w[i]);
	}
	int ans = 0;
	int t = 0;
	while(t < n){
		++ans;
		for(int i = n - 1; i >= t; --i){
			if(judge(t, i) != inf){
				t = i + 1;
				break;
			}
		}
	}

	/*
	rep(i, n){
		rep(j, n){
			printf("%d ", dp[i][j]);
		}
		printf("\n");
	}
	*/

	printf("%d\n", ans);
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4980
final_rank: 2