Description

JOI 君有 \(n\) 个装在手机上的挂饰, 编号为 \(1, 2, \ldots, n\). JOI 君可以将其中的一些装在手机上.

JOI 君的挂饰有一些与众不同----其中的一些挂饰附有可以挂其他挂件的挂钩. 每个挂件要么 直接挂在手机上, 要么挂在其他挂件的挂钩上. 直接挂在手机上的挂件最多有 \(1\) 个.

此外, 每个挂件有一个安装时会获得的喜悦值, 用一个整数来表示. 如果 JOI 君很讨厌某个 挂饰, 那么这个挂饰的喜悦值就是一个负数.

JOI 君想要最大化所有挂饰的喜悦值之和. 注意不必要将所有的挂钩都挂上挂饰, 而且一个 都不挂也是可以的.

Input

第一行一个整数 \(n\), 代表挂饰的个数.

接下来 \(n\) 行, 第 \(i\)\((1 \leq i \leq n)\) 有两个空格分隔的整数 \(A_i\)\(B_i\), 表示挂饰 \(i\)\(A_i\) 个挂钩, 安装后会获得 \(B_i\) 的喜悦值.

Output

输出一行一个整数, 表示手机上连接的挂饰总和的最大值.

Sample Input

5
0 4
2 -2
1 -1
0 1
0 3

Sample Output

5

Data Range

对于所有数据, 满足:\(1 \leq n \leq 2000, 0 \leq A_i \leq n, |B_i| \leq 10^6\)

Explanation

首先发现这样一个性质, 就是说只要确定好了选哪些挂饰 (并且需要的挂钩数不多于提供的 挂钩数), 总有一种办法使得我们可以把挂饰挂好, 因为这是一个树形结构, 然后简单构造 一下就可以了. 并且题目并没有让我们构造==

所以问题就变为确定一堆挂饰, 使得它们的需要的净挂钩数不多于 \(1\) 就可以了, 好了, 这就是一道十分水的背包问题了......

记得初始化要默认全是 \(-\infty\). ...... 不然就会像我一样死调好久 QAQ

Source Code


#include <iostream>
#include <cstdlib>
#include <cstdio>

#define maximize(__x,__y) __x=max(__x,__y)
using namespace std;
typedef long long lli;
const int maxn = 2010;
const lli infinit = 0x007f7f7f7f7f7f7fll;

template <typename _T>
class ext_array {
private:
    _T arr[maxn<<1];
    int n;
public:
    _T& operator [] (int _p) {
        return arr[min(max(_p,-n),n)+maxn];
    } void init(int _n, lli val) {
        n = _n; for (int i = 0; i < maxn<<1; i++)
            arr[i] = val;
        return ;
    }
};

int n;
lli a[maxn], b[maxn];
ext_array<lli> dp;

int main(int argc, char** argv)
{
    scanf("%d", &n);
    dp.init(n, -infinit);
    for (int i = 1; i <= n; i++)
        scanf("%lld%lld", &a[i], &b[i]);
    // Another EZ knapsack problem
    dp[0] = 0;
    for (int i = 1; i <= n; i++) {
        lli x = 1 - a[i];
        if (x > 0) // This costs more than it provides
            for (int j = n; j >= -n; j--)
                maximize(dp[j + x], dp[j] + b[i]);
        else // This generates more hooks
            for (int j = -n; j <= n; j++)
                maximize(dp[j + x], dp[j] + b[i]);
    }
    // Must use no more than 0 hooks
    lli res = 0;
    for (int i = -n; i <= 1; i++)
        maximize(res, dp[i]);
    printf("%lld\n", res);
    return 0;
}