题面

D. The Child and Sequence
time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at him. A lot of important things were lost, in particular the favorite sequence of Picks.

Fortunately, Picks remembers how to repair the sequence. Initially he should create an integer array a[1], a[2], ..., a[n]. Then he should perform a sequence of m operations. An operation can be one of the following:

  1. Print operation l, r. Picks should write down the value of .
  2. Modulo operation l, r, x. Picks should perform assignment a[i] = a[imod x for each i (l ≤ i ≤ r).
  3. Set operation k, x. Picks should set the value of a[k] to x (in other words perform an assignment a[k] = x).

Can you help Picks to perform the whole sequence of operations?

Input

The first line of input contains two integer: n, m (1 ≤ n, m ≤ 105). The second line contains n integers, separated by space: a[1], a[2], ..., a[n] (1 ≤ a[i] ≤ 109) — initial value of array elements.

Each of the next m lines begins with a number type .

  • If type = 1, there will be two integers more in the line: l, r (1 ≤ l ≤ r ≤ n), which correspond the operation 1.
  • If type = 2, there will be three integers more in the line: l, r, x (1 ≤ l ≤ r ≤ n; 1 ≤ x ≤ 109), which correspond the operation 2.
  • If type = 3, there will be two integers more in the line: k, x (1 ≤ k ≤ n; 1 ≤ x ≤ 109), which correspond the operation 3.
Output

For each operation 1, please print a line containing the answer. Notice that the answer may exceed the 32-bit integer.

Examples
input

Copy
5 5
1 2 3 4 5
2 3 5 4
3 3 5
1 2 5
2 1 3 3
1 1 3
output

Copy
8
5
input

Copy
10 10
6 9 6 7 6 1 10 10 9 5
1 3 9
2 7 10 9
2 5 10 8
1 4 7
3 3 7
2 7 9 9
1 2 4
1 6 6
1 5 9
3 1 10
output

Copy
49
15
23
1
9
Note

Consider the first testcase:

  • At first, a = {1, 2, 3, 4, 5}.
  • After operation 1, a = {1, 2, 3, 0, 1}.
  • After operation 2, a = {1, 2, 5, 0, 1}.
  • At operation 3, 2 + 5 + 0 + 1 = 8.
  • After operation 4, a = {1, 2, 2, 0, 1}.
  • At operation 5, 1 + 2 + 2 = 5.

简洁的题目翻译(取自luogu)

  给定数列,区间查询和,区间取模,单点修改。

  n,m小于10^5

题解

相当裸的一道线段树,但是思路相当神奇

首先我们会注意到,这题有要求区间修改和区间查询,学过线段树的神犇们可能就立刻会想到一系列诸如标记永久化,打lazytag等一系列高端操作来维护这颗线段树

但是实际上不用这样做哒qwq

否则你可能会像本蒟蒻一样在这道题上卡了一个半小时还一分都拿不到

因为这道题实际上是区间取模,取模实际上没办法像加法乘法一样做到利用一些lazytag的奇怪的做法把复杂度压成O(nlogn)

那么怎么做呢?

第四句话给了提示qwq

就是对要取模的区间暴力单点修改就行

这时候就有人要问了,这样暴力复杂度不对吧,当然不能,所以我们需要加一些玄学优化

首先我们要证明一些奇怪的东西

引理1:对一个数取模,如果能够取模,那么这个数至少会变成原来的\( \frac{1}{2} \),这非常的显然,所以我就懒得证明了23333

还是简单的证明一下,如果一个数能够被取模,则取模后它一定会变成小于模数的形式,如果模数大于原数的\( \frac {1}{2} \)则取模后结果一定会小于原数减去模数即结果一定小于原数的\( \frac {1}{2} \) ,现在考虑另一种情况,若模数小于原数的\( \frac {1}{2} \),则取模后的结果一定会小于模数,即结果一定小于等于原数的\( \frac {1}{2} \)

所以现在得证,一个数取模后规模至少缩小\( \frac{1}{2} \)

然后我们继续证明一些性质

引理2:若一个数被取模,则至多取模\( \lg N \)次

由引理1可知,一个数每次被取模规模都会缩小\( \frac{1}{2}\),所以只需要取模\( \lg N \)次就不可以继续取模了

现在有了这两个性质,我们再进行一些合理的猜想

取模运算很慢,那么为了减少运行时间,我们在能够不取模的时候应当不取模

引理3:若一个数小于模数,那么这个数取模后的结果和原数相等

显然,根据模除的性质,若这个数小于模数,那么除法运算最后的余数一定与原数相等

既然可能相等,我们就在出现相等情况时不取模就好了

因此,我们再在区间和之外多维护一个区间最大值即可,当模数大于区间最大值时,不对这个区间进行取模操作

下面就可以进行复杂度证明了

复杂度:O(nlogn)

证明:总共有n个数,因为一旦取模后结果可能不变就不会继续取模,所以每个数最多被取模\( \lg N \)次,所以最终的取模次数最多为nlogn次,时间复杂度为O(nlogn)

证毕

单点修改没什么好说的,现在我们就可以任性的取模了

贴代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = ;
long long maxm[MAXN<<],sum[MAXN<<],a[MAXN];
long long n,m;
void pushup(long long o){
maxm[o]=max(maxm[o<<],maxm[o<<|]);
sum[o]=(sum[o<<]+sum[o<<|]);
}
void build(long long l,long long r,long long o){
if(l==r){
sum[o]=a[l];
maxm[o]=a[l];
return;
}
long long mid=(l+r)>>;
build(l,mid,o<<);
build(mid+,r,o<<|);
pushup(o);
}
void updateadd(long long pos,long long l,long long r,long long o,long long v){
if(l==r){
sum[o]=v;
maxm[o]=v;
return;
}
long long mid=(l+r)>>;
if(pos<=mid)
updateadd(pos,l,mid,o<<,v);
else
updateadd(pos,mid+,r,o<<|,v);
pushup(o);
}
void updatemod(long long pos,long long l,long long r,long long o,long long v){
if(l==r){
sum[o]=sum[o]%v;
maxm[o]=maxm[o]%v;
}
long long mid=(l+r)>>;
if(pos<=mid)
updatemod(pos,l,mid,o<<,v);
else
updatemod(pos,mid+,r,o<<|,v);
pushup(o);
}
long long query(long long L,long long R,long long l,long long r,long long o){
if(L<=l&&r<=R){
return sum[o];
}
long long ans=,mid=(l+r)>>;
if(L<=mid)
ans+=query(L,R,l,mid,o<<);
if(R>mid)
ans+=query(L,R,mid+,r,o<<|);
return ans;
}
void update(long long L,long long R,long long l,long long r,long long o,long long v){
if(l==r){
sum[o]=sum[o]%v;
maxm[o]=maxm[o]%v;
return;
}
long long mid=(l+r)>>;
if(L<=mid&&maxm[o<<]>=v)
update(L,R,l,mid,o<<,v);
if(R>mid&&maxm[o<<|]>=v)
update(L,R,mid+,r,o<<|,v);
pushup(o);
}
int main(){
scanf("%lld %lld",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
build(,n,);
for(int i=;i<=m;i++){
int mode;
scanf("%d",&mode);
if(mode==){
long long lx,rx;
scanf("%lld %lld",&lx,&rx);
printf("%lld\n",query(lx,rx,,n,));
}
else if(mode==){
long long lx,rx,x;
scanf("%lld %lld %lld",&lx,&rx,&x);
update(lx,rx,,n,,x);
}
else{
long long k,x;
scanf("%lld %lld",&k,&x);
updateadd(k,,n,,x);
}
}
return ;
}

题解——CodeForces 438D The Child and Sequence的更多相关文章

  1. Codeforces 438D The Child and Sequence - 线段树

    At the children's day, the child came to Picks's house, and messed his house up. Picks was angry at ...

  2. Codeforces 438D The Child and Sequence

    题意:给定一个n个数的序列,完成以下3个操作: 1.给定区间求和 2.给定区间对x取模 3.单点修改 对一个数取模,这个数至少折半.于是我们记一个最大值max,如果x>max则不做处理. #in ...

  3. 2018.07.23 codeforces 438D. The Child and Sequence(线段树)

    传送门 线段树维护区间取模,单点修改,区间求和. 这题老套路了,对一个数来说,每次取模至少让它减少一半,这样每次单点修改对时间复杂度的贡献就是一个log" role="presen ...

  4. CodeForces 438D The Child and Sequence (线段树 暴力)

    传送门 题目大意: 给你一个序列,要求在序列上维护三个操作: 1)区间求和 2)区间取模 3)单点修改 这里的操作二很讨厌,取模必须模到叶子节点上,否则跑出来肯定是错的.没有操作二就是线段树水题了. ...

  5. 438D - The Child and Sequence

    D. The Child and Sequence time limit per test 4 seconds memory limit per test 256 megabytes input st ...

  6. CF(438D) The Child and Sequence(线段树)

    题意:对数列有三种操作: Print operation l, r. Picks should write down the value of . Modulo operation l, r, x. ...

  7. Codeforces 438D (今日gg模拟第二题) | 线段树 考察时间复杂度的计算 -_-|||

    Codeforces 438D The Child and Sequence 给出一个序列,进行如下三种操作: 区间求和 区间每个数模x 单点修改 如果没有第二个操作的话,就是一棵简单的线段树.那么如 ...

  8. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸

    D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  9. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模

    D. The Child and Sequence   At the children's day, the child came to Picks's house, and messed his h ...

随机推荐

  1. datetime处理日期和时间

    datetime.now() # 获取当前datetimedatetime.utcnow() datetime(2017, 5, 23, 12, 20) # 用指定日期时间创建datetime 一.将 ...

  2. 苹果企业版签名分发相关问题,蒲公英签名,fir.im分发,安装ipa设置信任

    苹果企业版签名分发相关问题,蒲公英签名,fir.im分发,安装ipa设置信任蒲公英 - 高效安全的内测应用发布.管理平台https://www.pgyer.com/app/signature分发版 2 ...

  3. js获取浏览器类型和版本信息

    bro () { let broName = 'Runing' let strStart = 0 let strStop = 0 let temp = '' let userAgent = windo ...

  4. Linux 执行文本保存报错 是使用了记事本等工具打开之后导致的

    dos2unix xx.bat    格式化下就好了 安装: yum install -y dos2unix

  5. 基于Redis实现分布式锁实战

    背景在很多互联网产品应用中,有些场景需要加锁处理,比如:秒杀,全局递增ID,楼层生成等等.大部分的解决方案是基于DB实现的,Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,且多客户端 ...

  6. Linux 查看端口使用情况

    之前查询端口是否被占用一直搞不明白,问了好多人,终于搞懂了,现在总结下: 1.netstat  -anp  |grep   端口号 如下,我以3306为例,netstat  -anp  |grep   ...

  7. 知乎上一个比较好的学习QT的公众号<<跟小豆君学Qt>>

    公众号网址:https://zhuanlan.zhihu.com/p/28472916

  8. 关于web.xml中配置Spring字符编码过滤器以解决中文乱码的问题

    当出现中文乱码问题,Spring中可以利用CharacterEncodingFilter过滤器解决,如下代码所示: <!-- Spring字符编码过滤器:解决中文乱码问题 --> < ...

  9. Linux环境nginx的配置

    1.创建nginx运行账户www并加入到www组,不允许www用户直接登录系统,查看创建. groupadd www useradd -g www www -s /bin/false tail /et ...

  10. 数据库的增、删、改、查 (CURD)

    增改查删可以用CURD来表示  增加:create  修改:update   查找:read      删除:delete 增加create :  insert +表名+values+(信息): in ...