Description

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

Input

第一行两个整数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)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

Output

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

Sample Input

7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7

Sample Output

2
35
8

HINT

【样例说明】

初始时数列为(1,2,3,4,5,6,7)。
经过第1次操作后,数列为(1,10,15,20,25,6,7)。
对第2次操作,和为10+15+20=45,模43的结果是2。
经过第3次操作后,数列为(1,10,24,29,34,15,16}
对第4次操作,和为1+10+24=35,模43的结果是35。
对第5次操作,和为29+34+15+16=94,模43的结果是8。

测试数据规模如下表所示
数据编号 1 2 3 4 5 6 7 8 9 10
N= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000
M= 10 1000 1000 10000 60000 70000 80000 90000 100000 100000

正解:线段树。

这题不难,但是容易出错,所以还是挺有意义的。

我们除了维护一个加法的标记以外,还要维护一个乘法的标记,当我们下放更新乘法标记时,被更新的那个区间的加法标记也要乘上对应的数(这个应该很显然吧。。)。并且我们下放的时候,要先下放乘法标记,再下放加法标记。于是我们就能完美地解决这题了。

 //It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define ls (x<<1)
#define rs (x<<1|1)
#define N (100010)
#define il inline
#define RG register
#define ll long long
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; ll sum[*N],m[*N],a[*N],n,Q,p; il ll gi(){
RG ll x=,q=; RG char ch=getchar();
while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar();
while (ch>='' && ch<='') x=x*+ch-,ch=getchar();
return q*x;
} il void build(RG ll x,RG ll l,RG ll r){
if (l==r){ sum[x]=gi(),m[x]=; return; }
RG ll mid=(l+r)>>;
build(ls,l,mid),build(rs,mid+,r);
sum[x]=sum[ls]+sum[rs]; m[x]=;
if (sum[x]>=p) sum[x]-=p; return;
} il void pushdown(RG ll x,RG ll l,RG ll r){
if (m[x]!=){
sum[ls]*=m[x],sum[ls]%=p;
sum[rs]*=m[x],sum[rs]%=p;
m[ls]*=m[x],m[ls]%=p;
m[rs]*=m[x],m[rs]%=p;
a[ls]*=m[x],a[ls]%=p;
a[rs]*=m[x],a[rs]%=p;
m[x]=;
}
if (a[x]!=){
RG ll mid=(l+r)>>;
sum[ls]+=(mid-l+)*a[x],sum[ls]%=p;
sum[rs]+=(r-mid)*a[x],sum[rs]%=p;
a[ls]+=a[x]; if (a[ls]>=p) a[ls]-=p;
a[rs]+=a[x]; if (a[rs]>=p) a[rs]-=p;
a[x]=;
}
return;
} il void mul(RG ll x,RG ll l,RG ll r,RG ll xl,RG ll xr,RG ll c){
if (xl<=l && r<=xr){
sum[x]*=c,sum[x]%=p;
m[x]*=c,m[x]%=p;
a[x]*=c,a[x]%=p;
return;
}
pushdown(x,l,r); RG ll mid=(l+r)>>;
if (xr<=mid) mul(ls,l,mid,xl,xr,c);
else if (xl>mid) mul(rs,mid+,r,xl,xr,c);
else mul(ls,l,mid,xl,mid,c),mul(rs,mid+,r,mid+,xr,c);
sum[x]=sum[ls]+sum[rs]; if (sum[x]>=p) sum[x]-=p; return;
} il void add(RG ll x,RG ll l,RG ll r,RG ll xl,RG ll xr,RG ll c){
if (xl<=l && r<=xr){
sum[x]+=(r-l+)*c,sum[x]%=p;
a[x]+=c; if (a[x]>=p) a[x]-=p;
return;
}
pushdown(x,l,r); RG ll mid=(l+r)>>;
if (xr<=mid) add(ls,l,mid,xl,xr,c);
else if (xl>mid) add(rs,mid+,r,xl,xr,c);
else add(ls,l,mid,xl,mid,c),add(rs,mid+,r,mid+,xr,c);
sum[x]=sum[ls]+sum[rs]; if (sum[x]>=p) sum[x]-=p; return;
} il ll query(RG ll x,RG ll l,RG ll r,RG ll xl,RG ll xr){
if (xl<=l && r<=xr) return sum[x];
pushdown(x,l,r); RG ll mid=(l+r)>>;
if (xr<=mid) return query(ls,l,mid,xl,xr);
else if (xl>mid) return query(rs,mid+,r,xl,xr);
else return (query(ls,l,mid,xl,mid)+query(rs,mid+,r,mid+,xr))%p;
} il void work(){
n=gi(),p=gi(); build(,,n); Q=gi();
for (RG ll i=,type,l,r,c;i<=Q;++i){
type=gi(),l=gi(),r=gi();
if (type==) c=gi(),mul(,,n,l,r,c);
if (type==) c=gi(),add(,,n,l,r,c);
if (type==) printf("%lld\n",query(,,n,l,r));
}
return;
} int main(){
File("seq");
work();
return ;
}

bzoj1798 [Ahoi2009]维护序列的更多相关文章

  1. 【线段树】Bzoj1798 [AHOI2009] 维护序列

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

  2. BZOJ1798[Ahoi2009]维护序列——线段树

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

  3. BZOJ_1798_[AHOI2009]维护序列_线段树

    BZOJ_1798_[AHOI2009]维护序列_线段树 题意:老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: ( ...

  4. [Luogu 2023] AHOI2009 维护序列

    [Luogu 2023] AHOI2009 维护序列 恕我冒昧这和线段树模板二有个琴梨区别? #include <cstdio> int n,m; long long p; class S ...

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

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

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

    洛谷 2023 [AHOI2009]维护序列 洛谷原题传送门 这个题也是一道经典的线段树模版(其实洛谷的模版二改一下输入顺序就能AC),其中包括区间乘法修改.区间加法修改.区间查询三个操作. 线段树的 ...

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

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

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

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

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

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

随机推荐

  1. canvas的beginPath和closePath分析总结,包括多段弧的情况

    参考博文: Html5 canvas画图教程17:论beginPath的重要性 先看两个例子 例1: <canvas id="myCanvas" width="30 ...

  2. 用虚拟机安装Linux系统的过程

    1.打开VMware->点击File->点击New Virtual Machine.. 2.我们选择Custom并点击Next 3.保持默认然后点next 4.选择图中所示内容,点Next ...

  3. java之JDK的环境变量配置

    JDK是什么? JDK是整个java开发的核心,它包含了JAVA的运行环境,JAVA工具和JAVA基础的类库. JDK包含的基本组件包括 java –--------> 运行编译后的java程序 ...

  4. 读headFirst设计模式 - 装饰者模式

    继承可以在复用父类代码的情况下扩展父类的功能,但同时继承增加了对象之间的耦合度,所以要慎用继承.那么有没有既能扩展父类的功能,又能使对象间解耦的方法呢?答案是肯定的,这就是我们今天要学习的装饰者模式. ...

  5. 来谈一谈------JavaScript对象

    1.window常用的属性: ①history ②location 2.history对象的方法: ①back() ②forward() ③go() 3.location对象的属性: ①host() ...

  6. java日期处理函数

    java中获取本年第一天的日期 public static Timestamp getYearFirstDay() { Calendar calendar = Calendar.getInstance ...

  7. 解决Antimalware Service Executable CPU占用高听语音

    windows8/8.1,WIN10自带的安全软件Windows defender还不错,基本可以不用装其他杀毒软件了. 但是其进程Antimalware Service Executable 出现C ...

  8. fastjson将json格式null转化空串

    生成JSON代码片段 Map < String , Object > jsonMap = new HashMap< String , Object>(); jsonMap.pu ...

  9. ASP.NET使用ajax实现分页局部刷新页面

    listview列表实现分页是非常容易的.ListView分页是非常简单的,加上一个DataPager控件,把ListView的ID赋予就可以了.最开始我就是这么写的.(网上有人说这样是伪分页?) & ...

  10. rgba()和opacity的使用

    rgba()表示 红 绿 蓝 alpha ,W3C指在原有的rgb颜色模型之后增加了 “alpha”参数,“可以让制定的颜色透明化”(rgb()上扩展的,其只可以设置颜色,而不能使设置的颜色透明化) ...