题目链接:
FZU 2163 多米诺骨牌
题意:
一条水平线上竖直放置
n
个多米诺骨牌,给出每个骨牌的坐标
数据范围:
n≤105,x[i]∈[10−8,108],y[i]∈[2,108]
分析:
用
ans[i]
表示第
i
个多米诺骨牌可以砸倒的最多多米诺骨牌数量。那么
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <climits>
#define lson(x) (x << 1)
#define rson(x) ((x << 1) | 1)
using namespace std;
typedef long long ll;
const int MAX_N = 100010;
int n, top;
int ans[MAX_N], sta[MAX_N], extra[MAX_N];
struct Domino {
int x, y, id;
bool operator < (const Domino& rhs) const {
return x < rhs.x;
}
}domino[MAX_N];
struct SegTree {
int left, right, value;
}segtree[MAX_N << 2];
void build(int left, int right, int cur)
{
segtree[cur].left = left, segtree[cur].right = right;
if (left == right) {
segtree[cur].value = left + 1;
return;
}
int mid = (left + right) >> 1;
build(left, mid, lson(cur));
build(mid + 1, right, rson(cur));
segtree[cur].value = max(segtree[lson(cur)].value, segtree[rson(cur)].value);
}
int query(int a, int b, int cur)
{
int left = segtree[cur].left, right = segtree[cur].right;
if (left == a && right == b) {
return segtree[cur].value;
}
int mid = (left + right) >> 1;
if (b <= mid) return query(a, b, lson(cur));
else if (a > mid) return query(a, b, rson(cur));
else {
return max(query(a, mid, lson(cur)), query(mid + 1, b, rson(cur)));
}
}
void update(int goal, int cur, int value)
{
int left = segtree[cur].left, right = segtree[cur].right;
if (left == right) {
segtree[cur].value = value;
return;
}
int mid = (left + right) >> 1;
if (goal <= mid) update(goal, lson(cur), value);
else update(goal, rson(cur), value);
segtree[cur].value = max(segtree[lson(cur)].value, segtree[rson(cur)].value);
}
int main()
{
while (~scanf("%d", &n)) {
for (int i = 0; i < n; ++i) {
scanf("%d%d", &domino[i].x, &domino[i].y);
domino[i].id = i;
}
sort(domino, domino + n);
build(0, n - 1, 1);
for (int i = 0; i < n; ++i) {
extra[i] = domino[i].x;
}
top = 0;
ans[domino[n - 1].id] = 1;
int x, y, pos, last, cur, value;
for (int i = n - 2; i >= 0; --i) {
x = domino[i].x, y = domino[i].y, cur = domino[i].id;
if (x + y > extra[n - 1]) pos = n - 1;
else {
pos = lower_bound(extra, extra + n, x + y) - extra - 1;
}
ans[cur] = query(i, pos, 1) - i;
update(i, 1, ans[cur] + i);
//printf("i = %d pos = %d cur = %d ans[cur] = %d\n", i, pos, cur, ans[cur]);
}
for (int i = 0; i < n; ++i) {
if (i) printf(" ");
printf("%d", ans[i]);
}
printf("\n");
}
return 0;
}