1798: [Ahoi2009]Seq 维护序列seq

Time Limit: 30 Sec  Memory Limit: 64 MB

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

  迷醉线段树题。

  这特么明显的线段树裸题,10w的数据,多组询问,支持区间修改和求和。

  所以就是在lazy标记上做文章。

  维护两个lazy标记,一个乘一个加。

  因为要满足运算符优先级,所以乘法必须马上实现在加法上。

  也就是说乘法的时候把加法的lazy也乘一遍。

  所以lazy的乘法操作都是当前节点已经搞完了的。

  那么lazy的下放就是要先乘再加了,不然会乘重复。

  理清楚优先级的限制之后很好做的。(真的吗?)

  反正我感觉乘的lazy就是加的lazy的lazy,除了一些维护答案的地方外... ...

  感觉越说越不清楚,代码糊上。

#include    <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <complex>
#include <stack>
#define ls (x<<1)
#define rs (x<<1|1)
#define LL long long int
#define dob double
using namespace std; const int N = 100010;
int n,P,m,T[N<<2],lazy_A[N<<2],lazy_M[N<<2]; int gi()
{
int x=0,res=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')res*=-1;ch=getchar();}
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*res;
} inline void build(int x,int l,int r){
if(l==r){T[x]=gi();return;}
int mid=(l+r)>>1;
build(ls,l,mid);build(rs,mid+1,r);
T[x]=(T[ls]+T[rs])%P;
lazy_A[x]=0;lazy_M[x]=1;
} inline void down(int x,int l,int r){
int mid=(l+r)>>1;
T[ls]=(1ll*T[ls]*lazy_M[x]+1ll*(mid-l+1)*lazy_A[x])%P;
T[rs]=(1ll*T[rs]*lazy_M[x]+1ll*(r-mid)*lazy_A[x])%P;
lazy_M[ls]=(1ll*lazy_M[ls]*lazy_M[x])%P;
lazy_M[rs]=(1ll*lazy_M[rs]*lazy_M[x])%P;
lazy_A[ls]=(1ll*lazy_A[ls]*lazy_M[x]+1ll*lazy_A[x])%P;
lazy_A[rs]=(1ll*lazy_A[rs]*lazy_M[x]+1ll*lazy_A[x])%P;
lazy_A[x]=0;lazy_M[x]=1;
return;
} inline void Mul(int x,int l,int r,int xl,int xr,int v){
if(l==xl && r==xr){
lazy_A[x]=1ll*lazy_A[x]*v%P;
lazy_M[x]=1ll*lazy_M[x]*v%P;
T[x]=1ll*T[x]*v%P;
return;
}
down(x,l,r);
int mid=(l+r)>>1;
if(xr<=mid)Mul(ls,l,mid,xl,xr,v);
else if(xl>mid)Mul(rs,mid+1,r,xl,xr,v);
else Mul(ls,l,mid,xl,mid,v),Mul(rs,mid+1,r,mid+1,xr,v);
T[x]=(T[ls]+T[rs])%P;
} inline void Add(int x,int l,int r,int xl,int xr,int v){
if(l==xl && r==xr){
lazy_A[x]=(lazy_A[x]+v)%P;
T[x]=(1ll*T[x]+1ll*(r-l+1)*v)%P;
return;
}
down(x,l,r);
int mid=(l+r)>>1;
if(xr<=mid)Add(ls,l,mid,xl,xr,v);
else if(xl>mid)Add(rs,mid+1,r,xl,xr,v);
else Add(ls,l,mid,xl,mid,v),Add(rs,mid+1,r,mid+1,xr,v);
T[x]=(T[ls]+T[rs])%P;
} inline int query(int x,int l,int r,int xl,int xr){
if(l==xl && r==xr)return T[x];
down(x,l,r);
int mid=(l+r)>>1;
if(xr<=mid)return query(ls,l,mid,xl,xr);
else if(xl>mid)return query(rs,mid+1,r,xl,xr);
else return (query(ls,l,mid,xl,mid)+query(rs,mid+1,r,mid+1,xr))%P;
} int main()
{
n=gi();P=gi();
build(1,1,n);
m=gi();
while(m--){
int type=gi();
if(type==1){
int l=gi(),r=gi(),c=gi();
Mul(1,1,n,l,r,c);
}
if(type==2){
int l=gi(),r=gi(),c=gi();
Add(1,1,n,l,r,c);
}
if(type==3){
int l=gi(),r=gi();
printf("%d\n",query(1,1,n,l,r));
}
}
return 0;
}

  

BZOJ1798 AHOI2009 维护数列的更多相关文章

  1. bzoj1798 [Ahoi2009]维护序列

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

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

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

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

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

  4. BZOJ1798: [Ahoi2009]Seq 维护序列seq[线段树]

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

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

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

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

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

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

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

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

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

  9. 【bzoj1500】 noi2005—维护数列

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 (题目链接) 题意 要求维护数列,操作有区间删除,区间插入,区间反转,区间修改,区间求和,求最 ...

随机推荐

  1. [flask/python/web] 解析flask web开发(Miguel著)一书第11章主页不显示博文表单的问题

    ---------------------------------------------以下内容2017.7.14更新---------------------------------------- ...

  2. 从零开始,轻松搞定SpringCloud微服务系列

    本系列博文目录 [微服务]之一:从零开始,轻松搞定SpringCloud微服务系列–开山篇(spring boot 小demo) [微服务]之二:从零开始,轻松搞定SpringCloud微服务系列–注 ...

  3. 小白关于python 对象和内存的关系的一些感悟和疑惑,望大神指教

    首先你输入了一个字符串,这个字符串是有大小的,电脑将其放在内存中,自动给其一个起始指针指向这个字符串的首位置,然后,你将这个字符串赋值给一个变量,这个对象又在内存中开辟出一个空间,这个变量会自动连接这 ...

  4. 【Android源码解析】View.post()到底干了啥

    emmm,大伙都知道,子线程是不能进行 UI 操作的,或者很多场景下,一些操作需要延迟执行,这些都可以通过 Handler 来解决.但说实话,实在是太懒了,总感觉写 Handler 太麻烦了,一不小心 ...

  5. 深度解剖sesssion运行原理

    已经大半年没有更新博客了,一方面有比博客更重要的事情要做,另外一方面也没有时间来整理知识,所以希望在接下来的日子里面能够多多的写博客来与大家交流 什么是session session的官方定义是:Se ...

  6. python的简介及入门

    前言 为何使用Python Python 是一种效率极高的语言.与其他众多的语言相比,实现相同功能,使用Python编写的程序包含的代码更少.Python的语法简单,易上手,使用Python编写的代码 ...

  7. 【算法】二叉查找树实现字典API

    参考资料 <算法(java)>                           — — Robert Sedgewick, Kevin Wayne <数据结构>       ...

  8. java多线程编程核心技术——第三章

    第一节等待/通知机制 1.1不使用等待/通知机制实现线程间的通讯 1.2什么是等待/通知机制 1.3等待/通知机制的实现 1.4方法wait()锁释放与notify()锁不释放 1.5当interru ...

  9. Linux中如何恢复rm命令误删除的文件之extundelete编译安装及使用

    1.下载extundelete包,安装依赖 我用的是Centos系统,在安装extundelete之前需要安装e2fsprogs,e2fsprogs-libs,e2fsprogs-devel. yum ...

  10. OpenXml读取word内容(三)

    内容和表格内容一起读: word内容: 代码: public static void ReadWordByOpenXml(string path) { using (WordprocessingDoc ...