题目描述

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

有 \(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;
}

LOJ #6029. 「雅礼集训 2017 Day1」市场 线段树维护区间除法的更多相关文章

  1. loj#6029. 「雅礼集训 2017 Day1」市场(线段树)

    题意 链接 Sol 势能分析. 除法是不能打标记的,所以只能暴力递归.这里我们加一个剪枝:如果区间内最大最小值的改变量都相同的话,就变成区间减. 这样复杂度是\((n + mlogn) logV\)的 ...

  2. #6029. 「雅礼集训 2017 Day1」市场 [线段树]

    考虑到每次除法,然后加法,差距会变小,于是维护加法lazytag即可 #include <cstdio> #include <cmath> #define int long l ...

  3. [LOJ 6029]「雅礼集训 2017 Day1」市场

    [LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...

  4. 【loj6029】「雅礼集训 2017 Day1」市场 线段树+均摊分析

    题目描述 给出一个长度为 $n$ 的序列,支持 $m$ 次操作,操作有四种:区间加.区间下取整除.区间求最小值.区间求和. $n\le 100000$ ,每次加的数在 $[-10^4,10^4]$ 之 ...

  5. 「雅礼集训 2017 Day1」市场 (线段树除法,区间最小,区间查询)

    老师说,你们暴力求除法也整不了多少次就归一了,暴力就好了(应该只有log(n)次) 于是暴力啊暴力,结果我归天了. 好吧,在各种题解的摧残下,我终于出了一篇巨好看(chou lou)代码(很多结构体党 ...

  6. loj #6032. 「雅礼集训 2017 Day2」水箱 线段树优化DP转移

    $ \color{#0066ff}{ 题目描述 }$ 给出一个长度为 \(n\) 宽度为 \(1\) ,高度无限的水箱,有 \(n-1\) 个挡板将其分为 \(n\) 个 \(1 - 1\) 的小格, ...

  7. [LOJ 6031]「雅礼集训 2017 Day1」字符串

    [LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...

  8. [LOJ 6030]「雅礼集训 2017 Day1」矩阵

    [LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...

  9. loj6029 「雅礼集训 2017 Day1」市场

    传送门:https://loj.ac/problem/6029 [题解] 考虑如果有一些近似连续的段 比如 2 2 2 3 3 3,考虑在除3意义下,变成0 0 0 1 1 1,相当于整体-2 又:区 ...

随机推荐

  1. fastjson,对象转json字符串的过程中对value为null的值的一些处理

    前言 fastjson是一个非常好用的java库,用于操作对象json序列化等等. 问题 最近在写代码的时候遇到问题,通过JSON.toJSONString方法将一个实体对象转为json字符串,转出来 ...

  2. HanLP的分词统计

    HanLP的分词效果鄙人研究了HanLP,他的分词效果确实还可以,而且速度也比较快,10的数据是9000毫秒 @SneakyThrows@Overridepublic LinkedHashMap< ...

  3. 多测师讲解python _函数的传递_高级讲师肖sir

    题目:   要求1.通过函数来实现       2.引用函数传递方法        3.引用返回值   有一个登录系统:账号admin  密码123456 验证码abc123    账号.密码.验证码 ...

  4. Mysql数据库分布式事务XA详解

    XA事务简介 XA 事务的基础是两阶段提交协议.需要有一个事务协调者来保证所有的事务参与者都完成了准备工作(第一阶段).如果协调者收到所有参与者都准备好的消息,就会通知所有的事务都可以提交了(第二阶段 ...

  5. 原生js实现一个自定义下拉单选选择框

    浏览器自带的原生下拉框不太美观,而且各个浏览器表现也不一致,UI一般给的下拉框也是和原生的下拉框差别比较大的,这就需要自己写一个基本功能的下拉菜单/下拉选择框了.最近,把项目中用到的下拉框组件重新封装 ...

  6. Jenkins:用maven在本地打包部署一个github的springboot项目(Jenkins 2.257)

    一,部署的准备工作 1,测试项目的地址: https://github.com/liuhongdi/profile 是一个空白项目 2,准备java环境:参见: https://www.cnblogs ...

  7. Pytest学习(三) - setup和teardown的使用

    一.前言 从文章标题可以看出,就是初始化和释放的操作,根据我的java习惯来学习pytest,个人感觉没差太多,理解上也不是很难. 哦,对了,差点跑题了,这个框架是基于Python语言的,在学习的时候 ...

  8. git 团队协作的一些命令

    1.开分支 git branch 新分支名 例如,在master分支下,新开一个开发分支: git branch dev 2.切换到新分支 git checkout 分支名 例如,在master分支下 ...

  9. 拿了十几个offer,怎样做选择?

    本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues. https://github.com/midou-tech/articles 最近收到好几个读者的咨询,关于如何选offer的 ...

  10. CTF-misc:老板,再来几道misc玩玩

    [BJDCTF 2nd]最简单的misc-y1ng 得到一个图片,提示格式损坏,修补一下文件头 然后得到一张图片 直接python16进制转字符串 >>> string = &quo ...