ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法

2020-11-14 08:01:33  阅读:193  来源: 互联网

标签:10 ch leq LOJ da 雅礼 && nans Day1


题目描述

从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落。

有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商贩的商品有一个价格\(a_i\),有两种政令:

\(l, r, c\),对于\(i \in [l, r], a_i \leftarrow a_i + c\)

\(l, r, d\),对于\(i \in [l, r], a_i \leftarrow \lfloor {a_i}/{d} \rfloor\)

现在有一个外乡的旅客想要了解贸易市场的信息,有两种询问方式:

给定 \(l, r\),求\(\min_{i \in [l, r]} a_i\)
给定 \(l, r\),求\(\sum_{i\in [l, r]} a_i\)

输入格式

第一行为两个空格隔开的整数 \(n, q\) 分别表示商贩个数和政令 \(+\) 询问个数。
第二行包含 \(n\) 个由空格隔开的整数\(a_0 \sim a_{n - 1}\)
接下来 \(q\) 行,每行表示一个操作,第一个数表示操作编号\(1 \sim 4\),接下来的输入和问题描述一致。

输出格式

对于每个 \(3\)、\(4\) 操作,输出询问答案。

样例

样例输入

10 10
-5 -4 -3 -2 -1 0 1 2 3 4
1 0 4 1
1 5 9 1
2 0 9 3
3 0 9
4 0 9
3 0 1
4 2 3
3 4 5
4 6 7
3 8 9

样例输出

-2
-2
-2
-2
0
1
1

数据范围与提示

对于 \(30\%\) 的数据,$n, q \leq 10 ^ 3 $;

对于 \(60\%\) 的数据,保证数据随机;

对于 \(100\%\) 的数据,\(1 \leq n, q \leq 10 ^ 5, 0 \leq l \leq r \leq n - 1, c \in [-10 ^ {4}, 10 ^ 4], d \in [2, 10 ^ 9]\)

分析

对于区间加、区间求和、区间求最小值的操作,像正常的线段树那样维护即可

对于区间除的操作,因为题目中要求向下取整,所以不能直接给整体除一个数

但是我们可以把除法转化为减法,把除以一个数变成减去一个数

这样,当一个区间内减去的数相同时,我们就可以给整体打一个标记

判断区间减去的数是否相同只需要判断区间最大值和区间最小值减去的值是否相同

如果不相同就一直下放,直到相同为止

这样的话我们再记录一个最大值就可以解决了

时间复杂度:\(O(可过)\)

代码

#include <cstdio>
#include <algorithm>
#include <cmath>
#define rg register
inline int read() {
    rg int x = 0, fh = 1;
    rg char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            fh = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * fh;
}
const int maxn = 1e5 + 5;
int a[maxn], n, q;
struct trr {
    int l, r, laz, mmin, mmax, siz;
    long long sum;
} tr[maxn << 2];
void push_up(int da) {
    tr[da].mmax = std::max(tr[da << 1].mmax, tr[da << 1 | 1].mmax);
    tr[da].mmin = std::min(tr[da << 1].mmin, tr[da << 1 | 1].mmin);
    tr[da].sum = tr[da << 1].sum + tr[da << 1 | 1].sum;
}
void push_down(int da) {
    if (tr[da].laz) {
        tr[da << 1].laz += tr[da].laz;
        tr[da << 1 | 1].laz += tr[da].laz;
        tr[da << 1].sum += 1LL * tr[da << 1].siz * tr[da].laz;
        tr[da << 1 | 1].sum += 1LL * tr[da << 1 | 1].siz * tr[da].laz;
        tr[da << 1].mmax += tr[da].laz;
        tr[da << 1 | 1].mmax += tr[da].laz;
        tr[da << 1].mmin += tr[da].laz;
        tr[da << 1 | 1].mmin += tr[da].laz;
        tr[da].laz = 0;
    }
}
void build(int da, int l, int r) {
    tr[da].l = l, tr[da].r = r, tr[da].siz = r - l + 1;
    if (tr[da].l == tr[da].r) {
        tr[da].mmin = tr[da].mmax = a[l];
        tr[da].sum = a[l];
        return;
    }
    rg int mids = (tr[da].l + tr[da].r) >> 1;
    build(da << 1, l, mids);
    build(da << 1 | 1, mids + 1, r);
    push_up(da);
}
void ad(int da, int l, int r, int val) {
    if (tr[da].l >= l && tr[da].r <= r) {
        tr[da].laz += val;
        tr[da].sum += 1LL * val * tr[da].siz;
        tr[da].mmin += val;
        tr[da].mmax += val;
        return;
    }
    push_down(da);
    rg int mids = (tr[da].l + tr[da].r) >> 1;
    if (l <= mids)
        ad(da << 1, l, r, val);
    if (r > mids)
        ad(da << 1 | 1, l, r, val);
    push_up(da);
}
int cxmin(int da, int l, int r) {
    if (tr[da].l >= l && tr[da].r <= r) {
        return tr[da].mmin;
    }
    push_down(da);
    rg int mids = (tr[da].l + tr[da].r) >> 1, nans = 2147483647;
    if (l <= mids)
        nans = std::min(nans, cxmin(da << 1, l, r));
    if (r > mids)
        nans = std::min(nans, cxmin(da << 1 | 1, l, r));
    return nans;
}
long long cxsum(int da, int l, int r) {
    if (tr[da].l >= l && tr[da].r <= r) {
        return tr[da].sum;
    }
    push_down(da);
    rg int mids = (tr[da].l + tr[da].r) >> 1;
    rg long long nans = 0;
    if (l <= mids)
        nans += cxsum(da << 1, l, r);
    if (r > mids)
        nans += cxsum(da << 1 | 1, l, r);
    return nans;
}
void cf(int da, int l, int r, int val) {
    if (tr[da].l >= l && tr[da].r <= r) {
        rg int now1 = floor((double)tr[da].mmin / val) - tr[da].mmin;
        rg int now2 = floor((double)tr[da].mmax / val) - tr[da].mmax;
        if (tr[da].l == tr[da].r) {
            tr[da].mmin = floor((double)tr[da].mmin / val);
            tr[da].sum = tr[da].mmax = tr[da].mmin;
        } else if (now1 == now2) {
            tr[da].mmin += now1;
            tr[da].mmax += now1;
            tr[da].laz += now1;
            tr[da].sum += 1LL * tr[da].siz * now1;
        } else {
            push_down(da);
            cf(da << 1, l, r, val);
            cf(da << 1 | 1, l, r, val);
            push_up(da);
        }
        return;
    }
    push_down(da);
    rg int mids = (tr[da].l + tr[da].r) >> 1;
    if (l <= mids)
        cf(da << 1, l, r, val);
    if (r > mids)
        cf(da << 1 | 1, l, r, val);
    push_up(da);
}
int main() {
    n = read(), q = read();
    for (rg int i = 1; i <= n; i++) {
        a[i] = read();
    }
    build(1, 1, n);
    rg int aa, bb, cc, dd;
    for (rg int i = 1; i <= q; i++) {
        aa = read(), bb = read(), cc = read();
        bb++, cc++;
        if (aa == 1) {
            dd = read();
            ad(1, bb, cc, dd);
        } else if (aa == 2) {
            dd = read();
            cf(1, bb, cc, dd);
        } else if (aa == 3) {
            printf("%d\n", cxmin(1, bb, cc));
        } else {
            printf("%lld\n", cxsum(1, bb, cc));
        }
    }
    return 0;
}

标签:10,ch,leq,LOJ,da,雅礼,&&,nans,Day1
来源: https://www.cnblogs.com/liuchanglc/p/13972196.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有