题面

从前有一个学校,在

O

n

e

I

n

D

a

r

k

\rm OneInDark

OneInDark 到任之前风气都是非常良好的,自从他来了之后,发布了一系列奇怪的要求,挟制了整个学校,导致风气的衰落。

n

n

n 个班级,从

0

n

1

0\sim n-1

0∼n−1 编号,每个班级的学生人数上限是

a

i

a_i

ai​。有两种要求;同时,校长助理别里手魔

H

a

n

d

I

n

D

e

v

i

l

HandInDevil

HandInDevil 想要了解实时的信息,有两种询问方式:

  1. (要求)

    l

    ,

    r

    ,

    c

    l,r,c

    l,r,c,对于

    i

    [

    l

    ,

    r

    ]

    ,

    a

    i

    a

    i

    +

    c

    i\in[l,r],a_i\leftarrow a_i+c

    i∈[l,r],ai​←ai​+c

  2. (要求)

    l

    ,

    r

    ,

    d

    l,r,d

    l,r,d,对于

    i

    [

    l

    ,

    r

    ]

    ,

    a

    i

    a

    i

    d

    i\in[l,r],a_i\leftarrow \left\lfloor\frac{a_i}{d}\right\rfloor

    i∈[l,r],ai​←⌊dai​​⌋

  3. (询问)给定

    l

    ,

    r

    l,r

    l,r,求

    min

    i

    [

    l

    ,

    r

    ]

    a

    i

    \min_{i\in[l,r]}a_i

    mini∈[l,r]​ai​

  4. (询问)给定

    l

    ,

    r

    l,r

    l,r,求

    i

    [

    l

    ,

    r

    ]

    a

    i

    \sum_{i\in[l,r]}a_i

    ∑i∈[l,r]​ai​

输入格式

第一行为两个空格隔开的整数

n

,

q

n,q

n,q 分别表示班级个数和要求 + 询问个数。
第二行包含

n

n

n 个由空格隔开的整数

a

0

a

n

1

a_0\sim a_{n-1}

a0​∼an−1​
接下来

q

q

q 行,每行表示一个操作,第一个数表示操作编号

1

4

1\sim4

1∼4,接下来的输入和问题描述一致。

输出格式

对于每个

3

,

4

3,4

3,4 操作,输出询问答案。

数据范围与提示

对于

100

%

100\%

100% 的数据,

1

n

,

q

1

0

5

,

0

l

r

n

1

,

c

[

1

0

4

,

1

0

4

]

,

d

[

2

,

1

0

9

]

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]

1≤n,q≤105,0≤l≤r≤n−1,c∈[−104,104],d∈[2,109]

题解

是一道运用运算规律的题。

操作有区间加区间除,要维护区间和以及区间最小值。最难办的是区间除。

我们会发现,两个数同时除以大于 1 的数,他们的差会在大约

log

\log

log 次运算后

1

\leq 1

≤1。因为下取整的原因,变为零很难做到,但是变为 1 可以很快。

如果一个区间最大值和最小值的差大于 1,那么就暴力递归下去,递归直到单点进行区间除,或者递归遇到一个极差小于等于 1 的区间时,进行下一步操作:

  • 如果极差为 0 ,那么就是一个区间赋值了。
  • 如果极差为 1,分情况讨论:若最大值和最小值除后下取整相等,那也是区间赋值,否则一定是最大值仍比最小值大 1 ,变化量相等,相当于区间加减。

我们在线段树上用

a

x

+

b

ax+b

ax+b 的形式表示懒标记,可以同时解决区间赋值和区间加减。

时间复杂度

O

(

n

log

2

n

)

\rm O(n\log^{_2}n)

O(nlog2​n) 。可以感性理解复杂度,也可以势能分析

CODE

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<ctime>
#include<queue>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 100005
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
#define eps (1e-4)
#define BI bitset<MAXN>
LL read() {
LL f=1,x=0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f*x;
}
void putpos(LL x) {
if(!x) return ;
putpos(x/10); putchar('0'+(x%10));
}
void putnum(LL x) {
if(!x) putchar('0');
else if(x < 0) putchar('-'),putpos(-x);
else putpos(x);
}
inline void AIput(LL x,char c) {
putnum(x); putchar(c);
}
int n,m,s,o,k;
int A[MAXN];
struct it{
LL s,lza,lzb,le;
LL ma,mi;
it(){s=le=0;lza=1;lzb=0;ma=mi=0;}
it(LL nm) {
s=ma=mi=nm; lza=1;lzb=0; le=1;
}
}tre[MAXN<<2];
void update(int a) {
int ls = a<<1,rs = a<<1|1;
tre[a].s = tre[ls].s + tre[rs].s;
tre[a].ma = max(tre[ls].ma,tre[rs].ma);
tre[a].mi = min(tre[ls].mi,tre[rs].mi);
tre[a].le = tre[ls].le + tre[rs].le;
return ;
}
void maketree(int a,int l,int r) {
tre[a] = it();
if(l == r) {
tre[a].s = A[l]; tre[a].le = 1;
tre[a].ma = tre[a].mi = A[l];
return ;
}
else {
int mid = (l + r) >> 1;
maketree(a<<1,l,mid); maketree(a<<1|1,mid+1,r);
update(a);
}return ;
}
void adda(int a,LL m,LL k) {
tre[a].s *= m;
tre[a].s += k*1ll*tre[a].le;
tre[a].ma *= m; tre[a].mi *= m;
tre[a].ma += k; tre[a].mi += k;
tre[a].lza *= m; tre[a].lzb *= m;
tre[a].lzb += k; return ;
}
void seta(int a,LL k) {
tre[a].s = k*1ll*tre[a].le;
tre[a].ma = tre[a].mi = k;
tre[a].lza = 0; tre[a].lzb = k; return ;
}
void sdiva(int a,LL k) {
LL Mx = tre[a].ma,Mi = tre[a].mi;
if(Mx > Mi+1) return ;
if(floor((DB)Mx/k) == floor((DB)Mi/k)) {
seta(a,floor((DB)Mx/k));
}
else {
LL mut = Mx - floor((DB)Mx/k);
adda(a,1,-mut);
}return ;
}
void pushdown(int a) {
if(tre[a].lza != 1 || tre[a].lzb != 0) {
adda(a<<1,tre[a].lza,tre[a].lzb);
adda(a<<1|1,tre[a].lza,tre[a].lzb);
tre[a].lza = 1; tre[a].lzb = 0;
}return ;
}
void addtree(int a,int l,int r,int al,int ar,LL c) {
if(l > r || al > r || ar < l) return ;
if(al >= l && ar <= r) {
adda(a,1,c); return ;
}
int mid = (al + ar) >> 1;
pushdown(a);
addtree(a<<1,l,r,al,mid,c);addtree(a<<1|1,l,r,mid+1,ar,c);
update(a); return ;
}
void divtree(int a,int l,int r,int al,int ar,LL d) {
if(l > r || al > r || ar < l) return ;
if(al >= l && ar <= r && tre[a].ma <= tre[a].mi+1) {
sdiva(a,d); return ;
}
if(al == ar) {
tre[a] = it(floor((DB)tre[a].s/d)); return ;
}
int mid = (al + ar) >> 1;
pushdown(a);
divtree(a<<1,l,r,al,mid,d); divtree(a<<1|1,l,r,mid+1,ar,d);
update(a); return ;
}
LL mintree(int a,int l,int r,int al,int ar) {
if(l > r || al > r || ar < l) return (LL)1e18;
if(al >= l && ar <= r) return tre[a].mi;
int mid = (al + ar) >> 1;pushdown(a);
return min(mintree(a<<1,l,r,al,mid),mintree(a<<1|1,l,r,mid+1,ar));
}
LL sumtree(int a,int l,int r,int al,int ar) {
if(l > r || al > r || ar < l) return 0;
if(al >= l && ar <= r) return tre[a].s;
int mid = (al + ar) >> 1;pushdown(a);
return sumtree(a<<1,l,r,al,mid) + sumtree(a<<1|1,l,r,mid+1,ar);
}
int main() {
n = read();m = read();
for(int i = 1;i <= n;i ++) {
A[i] = read();
}
maketree(1,1,n);
while(m --) {
k = read();
s = read()+1;o = read()+1;
if(k == 1) {
k = read();
addtree(1,s,o,1,n,k);
}
else if(k == 2) {
k = read();
divtree(1,s,o,1,n,k);
}
else if(k == 3) {
AIput(mintree(1,s,o,1,n),'\n');
}
else AIput(sumtree(1,s,o,1,n),'\n');
}
return 0;
}

LOJ6029「雅礼集训 2017 Day1」市场 (线段树)的更多相关文章

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

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

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

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

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

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

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

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

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

    题目描述 从前有一个贸易市场,在一位执政官到来之前都是非常繁荣的,自从他来了之后,发布了一系列奇怪的政令,导致贸易市场的衰落. 有 \(n\) 个商贩,从\(0 \sim n - 1\) 编号,每个商 ...

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

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

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

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

  8. 【loj6029】「雅礼集训 2017 Day1」市场&&【uoj#228】基础数据结构练习题

    题解: 这两道题加上区间取min max应该算线段树几道比较不寻常的题目 其实也是挺好理解的 对于区间/d 显然在log次后就会等于0 而我们注意到如果区间中数都相等那么就可以一起除 也就是说每个区间 ...

  9. 【LOJ6029】「雅礼集训 2017 Day1」市场(线段树裸题)

    点此看题面 大致题意: 维护序列,支持区间加法,区间除法(向下取整),区间求\(min\)和区间求和. 线段树维护区间除法 区间加法.区间求\(min\)和区间求和都是线段树基本操作,因此略过不提. ...

随机推荐

  1. 2021.06.12【NOIP提高B组】模拟 总结

    T1 题目大意:有 \(n\) 个点,到点 \(i\) 可以获得 \(A_i\) ,同时消耗 \(B_i\) 若当前价值小于 \(B_i\) 则不能到,问从 \(P\) 开始,任一点结束后的最大值. ...

  2. 使用PowerShell下载文件

    更新记录 本文迁移自Panda666原博客,原发布时间:2021年7月12日. 使用Invoke-WebRequest指令下载文件 [Net.ServicePointManager]::Securit ...

  3. ssh隧道连接的方式连接数据库

    最好用xshell做隧道连接,其他工具没接触过过 1.先新建一个会话 2.点进刚刚建好的连接,右击属性 3.点进隧道,添加,输入映射到本地的配置 4.完成之后用数据库连接工具连接即可 参考连接: ht ...

  4. BUUCTF-神秘龙卷风

    神秘龙卷风 通过提示知道压缩包密码是四位纯数字,通过爆破得到 得到一串编码 看样子应该是brainfuck编码 flag{e4bbef8bdf9743f8bf5b727a9f6332a8}

  5. 宝塔Linux面板安装教程

    宝塔Linux面板安装教程 安装要求: 内存:512M以上,推荐768M以上(纯面板约占系统60M内存) 硬盘:300M以上可用硬盘空间(纯面板约占20M磁盘空间) 系统:CentOS 7.1+ (U ...

  6. 【摸鱼神器】UI库秒变低代码工具——表单篇(一)设计

    前面说了列表的低代码化的方法,本篇介绍一下表单的低代码化. 内容摘要 需求分析. 定义 interface. 定义表单控件的 props. 定义 json 文件. 基于 el-form 封装,实现依赖 ...

  7. 面试突击62:group by 有哪些注意事项?

    注意:本文以下内容基于 MySQL 5.7 InnoDB 数据库引擎. 1.group by 后面不能加 where 在 MySQL 中,所有的 SQL 查询语法要遵循以下语法顺序: select f ...

  8. DBSync新增对MongoDB、ES的支持

    数据库同步工具DBSync近日进行了升级,最新版本为V1.9,新增了对MongoDB.Elasticseach(ES)的支持,具体情况:1.支持同型库之间的同步,如:MongoDB至MongoDB,E ...

  9. 基于 Github Actions 自动部署 Hexo 博客

    前言 前不久使用了 Hexo 搭建独立博客,我是部署在我的腾讯云轻量应用服务器上的,每次都需要 hexo deploy 然后打包.上传.解压和刷新 CDN,非常麻烦.我的服务器配置也不高 2C2G 无 ...

  10. docker多段构建nessus镜像

    1.构建基础镜像,主要做安装和获取注册号: FROM ubuntu:16.04 ADD Nessus-8.11.0-debian6_amd64.deb /tmp/Nessus-8.11.0-debia ...