FZU 2163 多米诺骨牌(线段树)

来源:互联网 发布:全自动手机降温软件 编辑:程序博客网 时间:2024/05/29 16:21

题目链接:
FZU 2163 多米诺骨牌
题意:
一条水平线上竖直放置n个多米诺骨牌,给出每个骨牌的坐标x[i]和高度y[i]。每个骨牌向右倒会砸到某些多米诺骨牌,如果多米诺骨牌(初始坐标x[i]和高度y[i])倒下,会导致所有在[x[i]+1x[i]+y[i]1]范围内的多米诺骨牌倒下。求每个骨牌最多可以砸倒多少骨牌?
数据范围:n105,x[i][108,108],y[i][2,108]
分析:
ans[i]表示第i个多米诺骨牌可以砸倒的最多多米诺骨牌数量。那么ans[i]是坐标x[j][x[i],x[i]+y[i]1]max(ans[j]+ji)。我们可以先按照横坐标排序,从后往前求解,用线段树更新结点ans[j]+j,求区间最大值。

#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;}
0 0
原创粉丝点击