传送门(洛谷)

传送门(bzoj)

题目

老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。

输入格式:

第一行两个整数N和P(1≤P≤1000000000)。
第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。
第三行有一个整数M,表示操作总数。
从第四行开始每行描述一个操作,输入的操作有以下三种形式:
操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。
操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。
操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

输出格式:

对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。

分析

参见洛谷线段树模板2,lazy标记记录两个值mul和add。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
long long n,m,mod;
struct node {
long long sum,add,mul;
}d[];
inline void build(long long le,long long ri,long long pos,long long wh,long long k){
d[wh].sum+=k;
d[wh].mul=;
if(le==ri)return;
long long mid=(le+ri)>>;
if(mid>=pos)build(le,mid,pos,wh<<,k);
else build(mid+,ri,pos,(wh<<)|,k);
}
inline void udm(long long le,long long ri,long long x,long long y,long long wh,long long k){
if(le>=x&&ri<=y){
d[wh].mul=d[wh].mul*k%mod;
d[wh].add=d[wh].add*k%mod;
d[wh].sum=d[wh].sum*k%mod;
return;
}
long long mid=(le+ri)>>;
long long t=d[wh].mul,s=d[wh].add;
d[wh].mul=,d[wh].add=;
d[wh<<].mul=d[wh<<].mul*t%mod;
d[wh<<].add=(d[wh<<].add*t%mod+s)%mod;
d[wh<<].sum=(d[wh<<].sum*t%mod+(mid-le+)*s%mod)%mod;
d[(wh<<)|].mul=d[(wh<<)|].mul*t%mod;
d[(wh<<)|].add=(d[(wh<<)|].add*t%mod+s)%mod;
d[(wh<<)|].sum=(d[(wh<<)|].sum*t%mod+(ri-mid)*s%mod)%mod;
if(mid>=x)udm(le,mid,x,y,wh<<,k);
if(mid<y)udm(mid+,ri,x,y,(wh<<)|,k);
d[wh].sum=(d[wh<<].sum+d[(wh<<)|].sum)%mod;
}
inline void uda(long long le,long long ri,long long x,long long y,long long wh,long long k){
if(le>=x&&ri<=y){
d[wh].add=(d[wh].add+k)%mod;
d[wh].sum=(d[wh].sum+(ri-le+)*k%mod)%mod;
return;
}
long long mid=(le+ri)>>;
long long t=d[wh].mul,s=d[wh].add;
d[wh].mul=,d[wh].add=;
d[wh<<].mul=d[wh<<].mul*t%mod;
d[wh<<].add=(d[wh<<].add*t%mod+s)%mod;
d[wh<<].sum=(d[wh<<].sum*t%mod+(mid-le+)*s%mod)%mod;
d[(wh<<)|].mul=d[(wh<<)|].mul*t%mod;
d[(wh<<)|].add=(d[(wh<<)|].add*t%mod+s)%mod;
d[(wh<<)|].sum=(d[(wh<<)|].sum*t%mod+(ri-mid)*s%mod)%mod;
if(mid>=x)uda(le,mid,x,y,wh<<,k);
if(mid<y)uda(mid+,ri,x,y,(wh<<)|,k);
d[wh].sum=(d[wh<<].sum+d[(wh<<)|].sum)%mod;
}
inline long long que(long long le,long long ri,long long x,long long y,long long wh){
if(le>=x&&ri<=y)return d[wh].sum%mod;
long long mid=(le+ri)>>,ans=;
long long t=d[wh].mul,s=d[wh].add;
d[wh].mul=,d[wh].add=;
d[wh<<].mul=d[wh<<].mul*t%mod;
d[wh<<].add=(d[wh<<].add*t%mod+s)%mod;
d[wh<<].sum=(d[wh<<].sum*t%mod+(mid-le+)*s%mod)%mod;
d[(wh<<)|].mul=d[(wh<<)|].mul*t%mod;
d[(wh<<)|].add=(d[(wh<<)|].add*t%mod+s)%mod;
d[(wh<<)|].sum=(d[(wh<<)|].sum*t%mod+(ri-mid)*s%mod)%mod;
if(mid>=x)ans=(ans+que(le,mid,x,y,wh<<))%mod;
if(mid<y)ans=(ans+que(mid+,ri,x,y,(wh<<)|))%mod;
d[wh].sum=(d[wh<<].sum+d[(wh<<)|].sum)%mod;
return ans;
}
int main()
{ long long i,j,k,x,y,z;
scanf("%lld%lld",&n,&mod);
for(i=;i<=n;i++){
scanf("%lld",&x);
build(,n,i,,x);
}
scanf("%lld",&m);
for(i=;i<=m;i++){
scanf("%lld",&k);
if(k==){
scanf("%lld%lld%lld",&x,&y,&z);
udm(,n,x,y,,z);
}else if(k==){
scanf("%lld%lld%lld",&x,&y,&z);
uda(,n,x,y,,z);
}else {
scanf("%lld%lld",&x,&y);
printf("%lld\n",que(,n,x,y,));
}
}
return ;
}

p2023&bzoj1798 维护序列的更多相关文章

  1. 洛谷 P2023 [AHOI2009]维护序列

    P2023 [AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中 ...

  2. 洛谷 P2023 [AHOI2009]维护序列 题解

    P2023 [AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列中 ...

  3. 洛谷P2023 [AHOI2009]维护序列(线段树区间更新,区间查询)

    洛谷P2023 [AHOI2009]维护序列 区间修改 当我们要修改一个区间时,要保证 \(ax+b\) 的形式,即先乘后加的形式.当将区间乘以一个数 \(k\) 时,原来的区间和为 \(ax+b\) ...

  4. 洛谷P3373 【模板】线段树 2 && P2023 [AHOI2009]维护序列——题解

    题目传送: P3373 [模板]线段树 2  P2023 [AHOI2009]维护序列 该题较传统线段树模板相比多了一个区间乘的操作.一提到线段树的区间维护问题,就自然想到了“懒标记”:为了降低时间复 ...

  5. P2023 [AHOI2009]维护序列 题解(线段树)

    题目链接 P2023 [AHOI2009]维护序列 解题思路 线段树板子.不难,但是...有坑.坑有多深?一页\(WA\). 由于乘法可能乘\(k=0\),我这种做法可能会使结果产生负数.于是就有了这 ...

  6. [洛谷P2023] [AHOI2009]维护序列

    洛谷题目链接:[AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列 ...

  7. BZOJ1798 维护序列seq

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 8058  Solved: 2964[Submit ...

  8. 【双标记线段树】bzoj1798维护序列seq

    一.题目 描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列 ...

  9. 【题解】洛谷P2023 [AHOI2009] 维护序列(线段树)

    洛谷P2023:https://www.luogu.org/problemnew/show/P2023 思路 需要2个Lazy-Tag 一个表示加的 一个表示乘的 需要先计算乘法 再计算加法 来自你谷 ...

随机推荐

  1. 什么是gitlab CI ?CI代表什么?

    CI是Continuous Integration的简称,就是持续集成的意思. 就是说你代码改动了,测试了,提交了,持续集成系统会自动构建(编译等等).持续集成的理念是每个提交的版本都应该是可交付的, ...

  2. java 中的拦截器和过滤器

    区别: 1.拦截器是基于java的反射机制的,而过滤器是基于函数回调 2.过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 3.拦截器只能对action请求起作用,而过滤器则可以对几 ...

  3. spring boot: EL和资源 (一般注入说明(二) @Service注解 @Component注解)

    @Service用于标注业务层组件 : 将当前类注册为spring的Bean @Controller用于标注控制层组件(如struts中的action) @Repository用于标注数据访问组件,即 ...

  4. idea集成spring+spring MVC+mybatis问题

    1.如果mybatis的xml文件放在java文件夹下(idea不会编译src的java目录的xml文件),需要在pom.xml中加入以下代码: <build> <resources ...

  5. 10 Python 数据类型—集合

    在Python set是基本数据类型的一种集合类型,它有可变集合(set())和不可变集合(frozenset)两种.创建集合set.集合set添加.集合删除.交集.并集.差集的操作都是非常实用的方法 ...

  6. Idea_学习_07_Idea常用配置

    二.参考资料 1.Android Studio 入门级教程(一)

  7. js的trim方法(转)

    写成类的方法格式如下:(str.trim();) <script language="javascript"> String.prototype.trim=functi ...

  8. C语言小程序(一)、判断三角型类型

    最近回炉重造C语言,陆续写一些比较短的代码,选择其中的一些贴到这里,都是在Linux下的代码,Windows未测试. 第一个判断三角形的类型,两个浮点型数据不能直接判断相等,为了输入方便一些,自己设置 ...

  9. noip2017列队(线段树)

    维护一个方阵,支持 1.删掉一个点,剩下的点先向左看齐再向前看齐 2.询问一个位置上是哪个点 $n,m,q \leq 3 \times 10^5$ sol: 我们每行前$m-1$列维护一个线段树,最后 ...

  10. ACM学习历程—FZU2195 检查站点(树形DP || 贪心)

    Description 在山上一共有N个站点需要检查,检查员从山顶出发去各个站点进行检查,各个站点间有且仅有一条通路,检查员下山前往站点时比较轻松,而上山时却需要额外的时间,问最后检查员检查完所有站点 ...