#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>

using namespace std;

// Dwa z najczesciej uzywanych typow o dlugich nazwach - ich skrocenie jest bardzo istotne
typedef vector<int> VI;
typedef long long LL;

// W programach bardzo rzadko mozna znalezc w pelni zapisana instrukcje petli. Zamiast niej, wykorzystywane sa trzy nastepujace makra:
// FOR - petla zwiekszajaca zmienna x od b do e wlacznie
#define FOR(x, b, e) for(int x = b; x <= (e); ++x)
// FORD - petla zmniejszajaca zmienna x od b do e wlacznie
#define FORD(x, b, e) for(int x = b; x >= (e); --x)
// REP - petla zwiekszajaca zmienna x od 0 do n. Jest ona bardzo czesto wykorzystywana do konstruowania i przegladania struktur danych
#define REP(x, n) for(int x = 0; x < (n); ++x)
// Makro VAR(v,n) deklaruje nowa zmienna o nazwie v oraz typie i wartosci zmiennej n. Jest ono czesto wykorzystywane podczas operowania na iteratorach struktur danych z biblioteki STL, ktorych nazwy typow sa bardzo dlugie
#define VAR(v, n) __typeof(n) v = (n)
// ALL(c) reprezentuje pare iteratorow wskazujacych odpowiednio na pierwszy i za ostatni element w strukturach danych STL. Makro to jest bardzo przydatne chociazby w przypadku korzystania z funkcji sort, ktora jako parametry przyjmuje pare iteratorow reprezentujacych przedzial elementow do posortowania.
#define ALL(c) (c).begin(), (c).end()
// Ponizsze makro sluzy do wyznaczania rozmiaru struktur danych STL. Uzywa sie go w programach, zamiast pisac po prostu x.size() z uwagi na fakt, iz wyrazenie x.size() jest typu unsigned int i w przypadku porownywania z typem int, w procesie kompilacji generowane jest ostrzezenie.
#define SIZE(x) ((int)(x).size())
// Bardzo pozyteczne makro, sluzace do iterowania po wszystkich elementach w strukturach danych STL.
#define FOREACH(i, c) for(VAR(i, (c).begin()); i != (c).end(); ++i)
// Skrot - zamiast pisac push_back podczas wstawiania elementow na koniec struktury danych, takiej jak vector, wystarczy napisac PB
#define PB push_back
// Podobnie - zamiast first bedziemy pisali po prostu ST
#define ST first
// a zamiast second - ND.
#define ND second
// Wartosc INF jest wykorzystywana jako reprezentacja nieskończonosci. Ma ona wartosc 1000000001, a nie 2147483647 (najwieksza wartosc typu int) ze wzgledu na dwa fakty - prosty zapis oraz brak przepelnienia wartosci zmiennej w przypadku dodawania dwoch nieskończonosci do siebie: ((int) 2147483647 + (int) 2147483647 = -2).
const LL INF = 1E18;
// Drzewo MinSummingTree umozliwia dodawanie elementow z przypisana im wartoscia oraz wyszukiwanie najwiekszej wartosci na dowolnym spojnym przedziale elementow

struct MinSummingTree {
    LL *mv, *cor, s;
    int *idx;
// Konstruktor przyjmuje jako parametr wysokosc konstruowanego drzewa (dziedzina elementow to [0..2^size-1])
    MinSummingTree(int size) {
	int l = 2*(s = 1<<size);
        mv = new LL[l];
        cor = new LL[l];
	idx = new int[l];
        REP(x,2*s) mv[x]=INF;
        REP(x,2*s) cor[x]=idx[x]=0;
	REP(x,s) idx[s+x] = x;
    }
// Destruktor zwalnia zaalokowana pamiec
    ~MinSummingTree() {
        delete[] mv;
        delete[] cor;
        delete[] idx;
    }
    void GetMin(LL &val, int &i) {
	val = mv[1];
	i = idx[1];
    }

    void Fixup(int p) {
        for(p>>=1; p>0; p>>=1) {
	    if(mv[p<<1] < mv[(p<<1)+1]) {
		mv[p] = cor[p] + mv[p<<1];
		idx[p] = idx[p<<1];
	    }
	    else {
		mv[p] = cor[p] + mv[(p<<1)+1];
		idx[p] = idx[(p<<1)+1];
	    }
	}
    }

// Funkcja zmienia wartosc elementu p na v
    void Set(int p, LL v) {
	// WARNING! ONLY VALID BEFORE FIRST COR UPDATE
        p+=s; mv[p]=v;
	Fixup(p);
    }

    void SetINF(int p) {
        p+=s; mv[p]=INF;
	Fixup(p);
    }

// Funkcja wyznacza najwieksza wartosc na przedziale elementow [p..k]
    void UpdateCor(int p, int k, LL dv) {
        p+=s;
        k+=s;
	int lp=p, lk=k;
// Przeszukiwanie drzewa rozpoczyna sie od lisci reprezentujacych elementy p i k. Dopoki wezel p jest rozny od wezla k...
        while(p<k) {
// Jesli przedzialy reprezentowane przez aktualne wezly p i k zawieraja sie calkowicie w  przeszukiwanym przedziale, to nastepuje aktualizacja wyniku
            if((p&1)==1) {
		cor[p] += dv;
		mv[p] += dv;
		p++;
	    }
            if((k&1)==0) {
		cor[k] += dv;
		mv[k] += dv;
		k--;
	    }

// Przejdz do ojcow wezlow p i k
            p>>=1;
            k>>=1;
        }

        if(p==k) {
	    cor[p] += dv;
	    mv[p] += dv;
	}

	Fixup(lp); Fixup(lk);
    }
};

struct Pr {
    LL a, b;
    bool operator<(const Pr &sec) const {
	return a > sec.a;
    }
};

int main() {
    int n;
    scanf("%d", &n);
    vector<Pr> v(n);
    REP(x, n) scanf("%lld %lld", &v[x].a, &v[x].b);
    sort(ALL(v));
//    vector<bool> sel(n);

    LL cumRes = 0;
    REP(selCnt, n) {
	LL selLeft = 0;
	LL cumStar = 0;
	LL bestV = -1, bestPos;
	REP(x, n) {
	    if (v[x].b == -1) {
		cumStar += v[x].a;
		selLeft += 1;
	    }
	    else {
		LL selRight = selCnt - selLeft;
		LL val = v[x].a * selRight + cumStar + v[x].b;
		if (val > bestV) {
		    bestV = val;
		    bestPos = x;
		}
	    }
	}
	v[bestPos].b = -1;
	cumRes += bestV;
	printf("%lld\n", cumRes); 
    }

    return 0;
}
