/*
* 01背包問題
* 把smart看做背包的體積,fun當做物品的價值,問題轉化為
* 求01背包的最大價值
* 狀態:dp[i] 表示體積si為i時的fun最大價值
* 狀態轉移:dp[i] = max(dp[i], dp[i-sj]+fj);
* 需要注意的是,背包價值都可能為負數,解決方案是整體左移
* 01 knapsack problem
* The volume of smart seen as a backpack, fun as the value of the items, the problem is transformed into
* Seek the maximum value of 01 backpack
* Status: dp [i] volume si fun when i maximum value
* The state transition: dp [i] = max (dp [i], dp [i-sj] + fj);
* Note backpack value may be negative, the solution is shifted left
*/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ORI 100010
#define MAXN 200020
#define INF 0x7ffffff
int dp[MAXN];
int dynamic_programming(int n)
{
int x, y, min_pos(ORI), max_pos(ORI), ans(0);
fill(dp, dp+MAXN, -INF); dp[ORI] = 0;
while( n -- ) {
scanf("%d %d", &x, &y);
if( x < 0 ) {
min_pos += x;
for(int i = min_pos; i <= max_pos+x; i ++) {
if( dp[i] < dp[i-x]+y ) {
dp[i] = dp[i-x]+y;
if( dp[i] >= 0 && i >= ORI ) {
ans = max(ans, dp[i]+i-ORI);
}
}
}
}
else {
max_pos += x;
for(int i = max_pos; i >= min_pos+x; i --) {
if( dp[i] < dp[i-x]+y ) {
dp[i] = dp[i-x]+y;
if( dp[i] >= 0 && i >= ORI ) {
ans = max(ans, dp[i]+i-ORI);
}
}
}
}
}
return ans;
}
int main(int argc, char const *argv[])
{
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
#endif
int n;
while( ~scanf("%d", &n) ) {
printf("%d\n", dynamic_programming(n));
}
return 0;
}