//URL: https://www.luogu.com.cn/problem/P1973
/*
吉林大学决定举办两场盛大的 NOI 嘉年华活动,分在两个不同的地点举办。每个嘉年华可能包含很多个活动,而每个活动只能在一个嘉年华中举办。
现在嘉年华活动的组织者小安一共收到了 nn 个活动的举办申请,其中第 ii 个活动的起始时间为 SiSi,活动的持续时间为 TiTi。这些活动都可以安排到任意一个嘉年华的会场,也可以不安排。
小安通过广泛的调查发现,如果某个时刻,两个嘉年华会场同时有活动在进行(不包括活动的开始瞬间和结束瞬间),那么有的选手就会纠结于到底去哪个会场,从而变得不开心。所以,为了避免这样不开心的事情发生,小安要求不能有两个活动在两个会场同时进行(同一会场内的活动可以任意进行)。
另外,可以想象,如果某一个嘉年华会场的活动太少,那么这个嘉年华的吸引力就会不足,容易导致场面冷清。所以小安希望通过合理的安排,使得活动相对较少的嘉年华的活动数量最大。
此外,有一些活动非常有意义,小安希望能举办,他希望知道,如果第 ii 个活动必须举办(可以安排在两场嘉年华中的任何一个),活动相对较少的嘉年华的活动数量的最大值
:::两个场馆不能有重叠的线段 但在一个场馆可以重叠 1.问线段数最小的 数目 最大是多少2.在必选某一线段时 线段数最小的 数目 最大是多少
t[i][j]:[i,j]完全覆盖的数量
f[i][j]:in_pos_1-i 第一个会场举办j情况下 另一个max几个 f[0][0]=0
g[i][j]:.......i-T 第一个会场举办j情况下 另一个max几个
1.->max{min(f[T][j],j)}
f[i][j]=max(f[k][j-t[k][i]],f[k][j]+t[k][i])
2.强制选 min(x+inter[L][R]+y,f[L][x]+g[R][y]) O(N^5)
ans[L][R]=max_{L,R,x,y} min(x+inter[L][R]+y,f[L][x]+g[R][y]) O(N^4)
f[L][x]和g[R][y]g[R][y]分别是关于xx和yy的减函数
所以对于固定的L,RL,R, 当xx变大时,最优的yy应该变小才能使答案更好
这样一来,将y作为一个随x增加而递减的指针即可时间复杂度为O(n3)
枚举时f[i][j<=n/2]
*/
/*
5
8 2
1 5
5 3
3 2
5 3
2
2
1
2
2
2
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string.h>
#include<queue>
#include<vector>
#include<bits/stdc++.h>
typedef long long ll;
#define ddd printf("-----------------------\n");
using namespace std;
const int maxn=4e2 +10;
const int mod=998244353;
const int inf=0x3f3f3f3f;
int n,a[maxn],b[maxn],u[maxn],v[maxn],p[maxn],q[maxn],t;
int inter[maxn][maxn],f[maxn][maxn],g[maxn][maxn],ans[maxn],txt[maxn][maxn];
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i],b[i]+=a[i],p[++t]=a[i],p[++t]=b[i];
sort(p+1,p+1+t);
q[1]=1;
for(int i=2;i<=t;i++){
if(p[i]!=p[i-1]) q[i]=q[i-1]+1;
else q[i]=q[i-1];
}
// t=q[t];
for(int i=1;i<=n;i++){
for(int j=1;j<=n<<1;j++){
if(a[i]==p[j]) u[i]=q[j];
if(b[i]==p[j]) v[i]=q[j];
}
}
t=q[t];//!!!!!!!!!!!!!!!!!!!!
for(int i=1;i<=t;i++)
for(int j=1;j<=t;j++)
for(int k=1;k<=n;k++)
if(i<=u[k]&&v[k]<=j)
inter[i][j]++;
for(int i=1;i<=t;i++){
for(int j=0;j<=n/2;j++){
f[i][j]=-inf; if(j==0) f[i][j]=inter[1][i];
for(int k=1;k<=i;k++){
f[i][j]=max(f[i][j],f[k][j]+inter[k][i]);
f[i][j]=max(f[i][j],f[k][max(0,j-inter[k][i])]);//j<=inter[][]is illegal ->f[k][0]
}
}
}
for(int i=t;i>=1;i--){
for(int j=0;j<=n/2;j++){
g[i][j]=-inf; if(j==0) g[i][j]=inter[i][t];
for(int k=i;k<=t;k++){
g[i][j]=max(g[i][j],g[k][j]+inter[i][k]);//???
g[i][j]=max(g[i][j],g[k][max(0,j-inter[i][k])]);
}
}
}
for(int i=0;i<=n;i++)
ans[0]=max(ans[0],min(f[t][i],i));
for(int l=1;l<=t;l++)
{
for(int r=1;r<=t;r++)
{
for(int x=0;x<=inter[1][l];x++)
{
for(int y=0;y<=inter[r][t];y++)
{
txt[l][r]=max(txt[l][r],min(inter[l][r]+x+y,f[l][x]+g[r][y]));
if(g[r][y]<=y) break;
}
if(f[l][x]<=x) break;
}
//if (inter[1][l]+inter[r][t]<ans[k]) break;
//if (inter[l][r]>inter[1][l]+inter[r][t]) break;
}
}
for(int i=1;i<=n;i++)
for(int l=u[i];l>=1;l--)
for(int r=v[i];r<=t;r++)
ans[i]=max(ans[i],txt[l][r]);
for(int i=0;i<=n;i++) cout<<ans[i]<<'\n';
return 0;
}