描述
题解
单调栈搞搞,不断更新左右区间,直到无法更新为止,在 51Nod 上见过一道类似的问题,不过那道题只需要一遍(update() + update_()
)即可解决,而这个问题涉及到两个更新函数可能会互相影响彼此,所以需要多次更新,直到无法更新为止。具体是哪道题我就记不大清楚了……
代码
#include <iostream>
#include <algorithm>
#include <stack>
#include <cstdio>
using namespace std;
typedef pair<int, int> pii;
const int MAXN = 1e5 + 10;
int n, flag;
int l[MAXN], r[MAXN];
pii a[MAXN], b[MAXN];
void update()
{
stack<int> si;
for (int i = 1; i <= n; i++) // 维护单调递增栈,更新 l[]
{
while (!si.empty() && si.top() >= l[i])
{
if (l[si.top()] < l[i])
{
l[i] = l[si.top()];
flag = 1;
}
si.pop();
}
si.push(i);
}
while (!si.empty())
{
si.pop();
}
for (int i = n; i >= 1; i--) // 维护单调递减栈,更新 r[]
{
while (!si.empty() && si.top() <= r[i])
{
if (r[si.top()] > r[i])
{
r[i] = r[si.top()];
flag = 1;
}
si.pop();
}
si.push(i);
}
while (!si.empty())
{
si.pop();
}
}
void update_()
{
stack<int> p;
for (int i = 1; i <= n; i++) // 维护单调递增栈,更新 r[]
{
while (!p.empty() && p.top() >= l[i])
{
if (r[p.top()] > r[i])
{
r[i] = r[p.top()];
flag = 1;
}
p.pop();
}
p.push(i);
}
while (!p.empty())
{
p.pop();
}
for (int i = n; i >= 1; i--) // 维护单调递减栈,更新 l[]
{
while (!p.empty() && p.top() <= r[i])
{
if (l[p.top()] < l[i])
{
l[i] = l[p.top()];
flag = 1;
}
p.pop();
}
p.push(i);
}
while (!p.empty())
{
p.pop();
}
}
int main()
{
while (cin >> n)
{
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &a[i].first, &a[i].second);
b[i] = a[i];
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; i++)
{
l[i] = (int)(lower_bound(a + 1, a + n + 1,
make_pair(a[i].first - a[i].second, 0)) - a);
r[i] = (int)(lower_bound(a + 1, a + n + 1,
make_pair(a[i].first + a[i].second, 0x3f3f3f3f)) - a - 1);
}
while (true)
{
flag = 0;
update();
update_();
if (!flag)
{
break;
}
}
for (int i = 1; i < n; i++)
{
int k = (int)(lower_bound(a + 1, a + n + 1, b[i]) - a);
printf("%d ", r[k] - l[k] + 1);
}
int k = (int)(lower_bound(a + 1, a + n + 1, b[n]) - a);
printf("%d\n", r[k] - l[k] + 1);
}
return 0;
}