1798: [Ahoi2009]Seq 维护序列seq

Time Limit: 30 Sec  Memory Limit: 64 MB
Submit: 7163  Solved: 2587
[Submit][Status][Discuss]

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

代码:
//加两个tag标记下传,注意乘的优先级高于加法所以加之前要乘完。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int MAXN=;
int n;
ll p,add[MAXN*],mul[MAXN*],sum[MAXN*];
void pushup(int rt)
{
sum[rt]=sum[rt<<]+sum[rt<<|];
if(sum[rt]>p) sum[rt]%=p;
}
void pushdown(int rt,int len)
{
if(mul[rt]==&&add[rt]==) return;
mul[rt<<]=(mul[rt<<]*mul[rt])%p;
add[rt<<]=(add[rt<<]*mul[rt]+add[rt])%p;
sum[rt<<]=(sum[rt<<]*mul[rt]+add[rt]*(len-(len>>)))%p;
mul[rt<<|]=(mul[rt<<|]*mul[rt])%p;
add[rt<<|]=(add[rt<<|]*mul[rt]+add[rt])%p;
sum[rt<<|]=(sum[rt<<|]*mul[rt]+add[rt]*(len>>))%p;
mul[rt]=;
add[rt]=;
}
void build(int rt,int l,int r)
{
add[rt]=;
mul[rt]=;
if(l==r){
scanf("%lld",&sum[rt]);
return;
}
int mid=(l+r)>>;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
pushup(rt);
}
void update(int rt,int l,int r,int ql,int qr,ll c,int ff)
{
if(ql<=l&&qr>=r){
if(ff==){
mul[rt]=(mul[rt]*c)%p;
sum[rt]=(sum[rt]*c)%p;
add[rt]=(add[rt]*c)%p;
}else{
add[rt]+=c;
sum[rt]=(sum[rt]+c*(r-l+))%p;
}
return;
}
pushdown(rt,r-l+);
int mid=(l+r)>>;
if(ql<=mid) update(rt<<,l,mid,ql,qr,c,ff);
if(qr>mid) update(rt<<|,mid+,r,ql,qr,c,ff);
pushup(rt);
}
ll query(int rt,int l,int r,int ql,int qr)
{
if(ql<=l&&qr>=r) return sum[rt];
pushdown(rt,r-l+);
int mid=(l+r)>>;
ll ans=;
if(ql<=mid) ans+=query(rt<<,l,mid,ql,qr);
if(qr>mid) ans+=query(rt<<|,mid+,r,ql,qr);
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
scanf("%d%lld",&n,&p);
build(,,n);
int m,op,x,y;
ll z;
scanf("%d",&m);
while(m--){
scanf("%d",&op);
if(op==){
scanf("%d%d%lld",&x,&y,&z);
update(,,n,x,y,z,);
}else if(op==){
scanf("%d%d%lld",&x,&y,&z);
update(,,n,x,y,z,);
}else{
scanf("%d%d",&x,&y);
ll ans=query(,,n,x,y);
printf("%lld\n",ans%p);
}
}
return ;
}

bzoj 1798 线段树的更多相关文章

  1. BZOJ 1798 (线段树||分块)的标记合并

    我原来准备做方差的.. 结果发现不会维护两个标记.. 就是操作变成一个 a*x+b ,每次维护a , b 即可 加的时候a=1 ,b=v 乘的时候a=v ,b=0 #include <cstdi ...

  2. bzoj 3999 线段树区间提取 有序链剖

    看错题目了,想成每个城市都可以买一个东西,然后在后面的某个城市卖掉,问最大收益.这个可以类似维护上升序列的方法在O(nlog^3n)的时间复杂度内搞定 这道题用到的一些方法: 1. 可以将有关的线段提 ...

  3. bzoj 3211 线段树

    开方操作最多进行5次就可以把出现的任何数变成1. 所以用线段树暴力修改,以后修改时只需看一下是否当前区间都是0或1,如果是那么就直接返回. /***************************** ...

  4. bzoj 1018 线段树维护连通性

    本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护. 对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边 ...

  5. bzoj 3212 线段树

    裸的线段树 /************************************************************** Problem: User: BLADEVIL Langua ...

  6. bzoj 2120 线段树套平衡树

    先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心..... 首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有, 但是能给我们一 ...

  7. bzoj 1901 线段树套平衡树+二分答案查询

    我们就建一颗线段树,线段树的每一个节点都是一颗平衡树,对于每个询问来说,我们就二分答案, 查询每个二分到的mid在这个区间里的rank,然后就行了 /************************* ...

  8. BZOJ 1012 线段树||单调队列

    非常裸的线段树  || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件 ...

  9. BZOJ 3681 线段树合并+网络流

    思路: 暴力建图有n*m条边 考虑怎么优化 (那就只能加个线段树了呗) 然后我就不会写了..... 抄了一波题解 //By SiriusRen #include <bits/stdc++.h&g ...

随机推荐

  1. 感谢Thunder团队

    不知不觉中,团队开发的beta版本都已经结束.开发的路上我们一起解决了很多难题,相互帮助走到了现在. 首先我想感谢组长王航.认真负责合理分配任务,使得我们每次发布都可以顺利并且按时完成.感谢胡佑蓉,李 ...

  2. 实验三 敏捷开发与XP实践 实验报告 20135232王玥

    一.实验内容 1. XP基础 2. XP核心实践 3. 相关工具 二.实验要求 1.没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程 2. ...

  3. "重力锁屏"Beta版使用说明

    一.产品介绍 重力锁屏是基于android系统的一款锁屏软件.它利用重力感应器来判断用户的动作从而自动锁屏亮屏,是锁屏软件的一大创新.相比传统的锁屏软件,“重力锁屏”从可操作性.方便性.功能全面性都有 ...

  4. Sqlite数据库初步的了解

    转载与:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0714/1438.html    来自:泡在网上的日子. 和其他数据库一 ...

  5. Task 9 从用户界面和体验分析“360极速浏览器”

    我目前使用的浏览器是360极速浏览器,下面将针对用户界面.记住用户选择.短期刺激.长期使用的好处坏处.不要让用户犯简单的错误四个方面对其进行评估: 1.用户界面: 01 可视性原则--网络没有连接或者 ...

  6. java微信开发之接口连接

    个人学习注册订阅号就行,把资料尽可能完善,不然开发时权限不够,然后登陆,点击订阅号然后扫码就可以微信关注.

  7. Code128

    条形码 条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符.常见的条形码是由反射率相差很大的黑条(简称条)和白条(简称空)排成的平行线图案.条形 ...

  8. WPF四则运算《《《《《策略模式

    设计思路:           因为之前没有用过WPF,听说和window窗体语法类似,就想着仿照之前的Window窗体做的,首先用三个textbox存储数据,添加一个comboBox,利用索引选择运 ...

  9. 软工网络15团队作业8——Beta阶段敏捷冲刺(day1)

    第 1 篇 Scrum 冲刺博客 1. 介绍小组新加入的成员,Ta担任的角色 --给出让ta担当此角色的理由 小组新加入的成员:3085叶金蕾 担任的角色:测试/用户体验/开发 理由:根据小组讨论以及 ...

  10. input、textArea实时显示剩余可输入的字数

    <h2>实时显示剩余可输入的字数(字母,数字,中文都算一个字)</h2> <h>昵称:</h> <div> <input type=& ...