【bzoj1798】[Ahoi2009]Seq 维护序列seq
大意:一个数组,三个操作,第一种是区间[a,b]每个数乘乘,第二种是区间[a,b]每个数加c,第三种是查询[a,b]区间的和并对p取摸。
两种操作就不能简单的只往下传标记。每次传乘法标记时,要把加法标记同时乘上乘法标记,例如某个区间先进来一个加法标记add,之后又进来一个乘法标记mul。
那么结果为(x+add)*mul=x*mul+add*mul。这样向下传标记的时候就相对独立。递归边界更新加法标记之前先乘上该节点的mul,左右儿子down的时候先将儿子的add乘上本节点的mul。
最后说一下sum,比如本节点的存在加法标记x和乘法标记y,并且是先加上x,再乘上y,则左儿子的sum要更新为(sum+x)*y。由于乘法标记传到本节点的时候更新了加法标记,x =x*y,所以sum[o<<1]=(左区间的长度*x)+sum[o<<1]*y。
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std; typedef long long LL; #define N 100010 int n,m;
int askd,al,ar,ask;
LL p; LL add[N<<],sum[N<<],mul[N<<]; void pushup(int now)
{
sum[now]=(sum[now<<]+sum[now<<|])%p;
} void pushdown(int now,int d)
{
if (add[now]!= || mul[now]!=)
{
mul[now<<]=mul[now<<]*mul[now]%p;
mul[now<<|]=mul[now<<|]*mul[now]%p;
add[now<<]=(add[now]+add[now<<]*mul[now])%p;
add[now<<|]=(add[now]+add[now<<|]*mul[now])%p;
sum[now<<]=(add[now]*(d-(d>>))+sum[now<<]*mul[now])%p;
sum[now<<|]=(add[now]*(d>>)+sum[now<<|]*mul[now])%p;
add[now]=;
mul[now]=;
}
} void build(int nowl,int nowr,int now)
{
sum[now]=;
mul[now]=;
if (nowl==nowr)
{
scanf("%lld",&sum[now]);
return ;
}
int mid=(nowl+nowr)>>;
build(nowl,mid,now<<);
build(mid+,nowr,now<<|);
pushup(now);
} void updata_mul(int nowl,int nowr,int now,int l,int r,int c)
{
if (nowl>=l && nowr<=r)
{
add[now]=add[now]*c%p;
sum[now]=sum[now]*c%p;
mul[now]=mul[now]*c%p;
return ;
}
pushdown(now,nowr-nowl+);
int mid=(nowl+nowr)>>;
if (l<=mid)
updata_mul(nowl,mid,now<<,l,r,c);
if (r>mid)
updata_mul(mid+,nowr,now<<|,l,r,c);
pushup(now);
} void updata_add(int nowl,int nowr,int now,int l,int r,int c)
{
if (nowl>=l && nowr<=r)
{
add[now]=(add[now]+c)%p;
sum[now]=(sum[now]+c*(nowr-nowl+))%p;
return ;
}
pushdown(now,nowr-nowl+);
int mid=(nowl+nowr)>>;
if (l<=mid)
updata_add(nowl,mid,now<<,l,r,c);
if (r>mid)
updata_add(mid+,nowr,now<<|,l,r,c);
pushup(now);
} LL query(int nowl,int nowr,int now,int l,int r)
{
LL res();
if (nowl>=l && nowr<=r)
return sum[now];
pushdown(now,nowr-nowl+);
int mid=(nowl+nowr)>>;
if (l<=mid)
res=(res+query(nowl,mid,now<<,l,r))%p;
if (r>mid)
res=(res+query(mid+,nowr,now<<|,l,r))%p;
return res;
} int main()
{
scanf("%d%lld",&n,&p);
build(,n,);
scanf("%d",&m);
while (m--)
{
scanf("%d",&askd);
if (askd==)
{
scanf("%d%d%d",&al,&ar,&ask);
updata_mul(,n,,al,ar,ask);
}
if (askd==)
{
scanf("%d%d%d",&al,&ar,&ask);
updata_add(,n,,al,ar,ask);
}
if (askd==)
{
scanf("%d%d",&al,&ar);
printf("%lld\n",query(,n,,al,ar));
}
}
return ;
}
【bzoj1798】[Ahoi2009]Seq 维护序列seq的更多相关文章
- BZOJ1798: [Ahoi2009]Seq 维护序列seq[线段树]
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 5504 Solved: 1937[Submit ...
- BZOJ 1798: [Ahoi2009]Seq 维护序列seq( 线段树 )
线段树.. 打个 mul , add 的标记就好了.. 这个速度好像还挺快的...( 相比我其他代码 = = ) 好像是#35.. ---------------------------------- ...
- 1798: [Ahoi2009]Seq 维护序列seq
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 2930 Solved: 1087[Submit ...
- bzoj 1798: [Ahoi2009]Seq 维护序列seq (线段树 ,多重标记下放)
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 7773 Solved: 2792[Submit ...
- bzoj 1798: [Ahoi2009]Seq 维护序列seq 线段树 区间乘法区间加法 区间求和
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeO ...
- Bzoj 1798: [Ahoi2009]Seq 维护序列seq(线段树区间操作)
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小可 ...
- BZOJ1798[Ahoi2009]Seq 维护序列seq 题解
题目大意: 有长为N的数列,有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值. ...
- 【bzoj1798】[Ahoi2009]Seq 维护序列seq 线段树
题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一 ...
- 【分块】bzoj1798 [Ahoi2009]Seq 维护序列seq
分块,打标记,维护两个标记:乘的 和 加的. 每次 区间乘的时候,对 乘标记 和 加标记 都 乘上那个值. 每次 区间加的时候 对 加标记 加上那个值. (ax+b)*v=axv+bv.开 long ...
- [bzoj1798][Ahoi2009]Seq 维护序列seq ([洛谷P3373]【模板】线段树 2)
题目大意:有$n$个数,有$m$个操作,有三种: $1\;l\;r\;x:$把区间$[l,r]$内的数乘上$x$ $2\;l\;r\;x:$把区间$[l,r]$内的数加上$x$ $3\;l\;r:$询 ...
随机推荐
- 第2节 mapreduce深入学习:7、MapReduce的规约过程combiner
第2节 mapreduce深入学习:7.MapReduce的规约过程combiner 每一个 map 都可能会产生大量的本地输出,Combiner 的作用就是对 map 端的输出先做一次合并,以减少在 ...
- python 获取路径
获取目录路径和文件路径 import osfor root, dirs, files in os.walk(".", topdown=False): # ‘.’为获取脚本所在路径下 ...
- extjs动态添加列
可以根据日期,动态的插入一列 controller层: StdDayWordQuery:function(btn,event){ var form=Ext.getCmp('queryFormSDW') ...
- js 技巧 (七)JS代码判断集锦(之一)
JS代码判断集锦(之一) ~~~~~~~~~~~~~~~~~~ <script language="JavaScript"> function checkid(iden ...
- Linux htop工具使用详解【转】
原文地址: http://www.cnphp6.com/archives/65078 一.Htop的使用简介 大家可能对top监控软件比较熟悉,今天我为大家介绍另外一个监控软件Htop,姑且称之为to ...
- mysql错误Error(1133): Can’t find any matching row in the use
执行插入用户语句没有问题,但是执行权限赋值的时候提示:1133 - Can't find any matching row in the user table; 解决办法:插入新的用户成功时,需要刷新 ...
- ruby 第五次作业 part 1(分类、排序)
movies_controller.rb class MoviesController < ApplicationController def movie_params params.requi ...
- python实现tcp文件下载器
服务器端代码 import socket import os import threading # 处理客户端请求下载文件的操作(从主线程提出来的代码) def deal_client_request ...
- Fiddler抓取https相关设置
转自:https://www.cnblogs.com/joshua317/p/8670923.html 很多使用fiddler抓包,对于http来说不需太多纠结,随便设置下就能用,但是抓取https就 ...
- CentOS 7.1安装GNOME,开启VNC Server
版权声明:本文为博主原创文章,未经博主允许不得转载. A.准备: 1.安装GNOME Desktop yum groupinstall 'GNOME Desktop' 2.确认GNOME Deskto ...