《算法竞赛进阶指南》打卡活动 #0x00 基本算法

Posted kisekipurin2019

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法竞赛进阶指南》打卡活动 #0x00 基本算法相关的知识,希望对你有一定的参考价值。

101. 最高的牛

题目链接:https://www.acwing.com/problem/content/103/

作为一个银牌水平的主演数据结构的演员来说,这题现在发现非常好想,每个牛分配一个优先度。我搞一个区间线段树,每次update中间一段使得他们的优先度整体下降到比两端中较小的优先度还要小。然后反过来按照优先度分配身高。哈哈!根本不需要什么算法。不过每次都不询问为什么要线段树呢?差分不香吗?当然不香,每次询问当前的优先度啊!

const int MAXN = 10000;

int res[MAXN + 5];

struct SegmentTree {
#define ls (o<<1)
#define rs (o<<1|1)
    static const int MAXN = 10000;
    static const int INF = 0x3f3f3f3f;
    int ma[(MAXN << 2) + 5];
    int lz[(MAXN << 2) + 5];

    void PushUp(int o) {
        ma[o] = max(ma[ls], ma[rs]);
    }

    void PushDown(int o, int l, int r) {
        if(lz[o]) {
            lz[ls] += lz[o];
            lz[rs] += lz[o];
            //int m = l + r >> 1;
            ma[ls] += lz[o];
            ma[rs] += lz[o];
            lz[o] = 0;
        }
    }

    void Build(int o, int l, int r, int mx) {
        if(l == r) {
            ma[o] = mx;
        } else {
            int m = l + r >> 1;
            Build(ls, l, m, mx);
            Build(rs, m + 1, r, mx);
            PushUp(o);
        }
        lz[o] = 0;
    }

    void Update(int o, int l, int r, int ql, int qr, int v) {
        if(ql <= l && r <= qr) {
            lz[o] += v;
            ma[o] += v;
        } else {
            PushDown(o, l, r);
            int m = l + r >> 1;
            if(ql <= m)
                Update(ls, l, m, ql, qr, v);
            if(qr >= m + 1)
                Update(rs, m + 1, r, ql, qr, v);
            PushUp(o);
        }
    }

    int QueryMax(int o, int l, int r, int ql, int qr) {
        if(ql <= l && r <= qr) {
            return ma[o];
        } else {
            PushDown(o, l, r);
            int m = l + r >> 1;
            int res = -INF;
            if(ql <= m)
                res = QueryMax(ls, l, m, ql, qr);
            if(qr >= m + 1)
                res = max(res, QueryMax(rs, m + 1, r, ql, qr));
            return res;
        }
    }
#undef ls
#undef rs
} st;

pii a[MAXN + 5];
int ans[MAXN + 5];

void test_case() {
    int n, p, h, m;
    scanf("%d%d%d%d", &n, &p, &h, &m);
    st.Build(1, 1, n, n);
    while(m--) {
        int l, r;
        scanf("%d%d", &l, &r);
        if(l > r)
            swap(l, r);
        if(l == r || l == r - 1)
            continue;
        int mi = min(st.QueryMax(1, 1, n, l, l), st.QueryMax(1, 1, n, r, r));
        int ma = st.QueryMax(1, 1, n, l + 1, r - 1);
        if(ma < mi)
            continue;
        int d = ma - (mi - 1);
        st.Update(1, 1, n, l + 1, r - 1, -d);
    }
    for(int i = 1; i <= n; ++i)
        a[i] = {st.QueryMax(1, 1, n, i, i), i};
    sort(a + 1, a + 1 + n, greater<pii>());
    ans[a[1].second] = h;
    for(int i = 2; i <= n; ++i) {
        if(a[i].first == a[i - 1].first)
            ans[a[i].second] = h;
        else
            ans[a[i].second] = --h;
    }
    for(int i = 1; i <= n; ++i)
        printf("%d
", ans[i]);
    return;
}

以上是关于《算法竞赛进阶指南》打卡活动 #0x00 基本算法的主要内容,如果未能解决你的问题,请参考以下文章

算法竞赛进阶指南 0x00

《算法竞赛进阶指南》0x00 汉诺塔四塔问题 递推关系

《算法竞赛进阶指南》0x03差分

《算法竞赛进阶指南》0x32约数 余数之和

算法竞赛进阶指南0x04 二分

《算法竞赛进阶指南》0x32约数