题目描述

如题,已知一个数列,你需要进行下面三种操作:

1.将某区间每一个数乘上x

2.将某区间每一个数加上x

3.求出某区间每一个数的和

输入输出格式

输入格式:

第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

输出格式:

输出包含若干行整数,即为所有操作3的结果。

输入输出样例

输入样例#1: 复制

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

输出样例#1: 复制

17
2

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据已经过加强^_^)

样例说明:

故输出应为17、2(40 mod 38=2)

AC代码

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <limits.h>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <string>
#define ll long long
#define ull unsigned long long
#define ms(a) memset(a,0,sizeof(a))
#define pi acos(-1.0)
#define INF 0x7f7f7f7f
#define lson o<<1
#define rson o<<1|1
const double E=exp(1);
const ll maxn=1e6+10;
using namespace std;
ll n,m,mod;
struct wzy
{
ll left,right,len;
ll value;
ll lazy;//加法
ll lazy1;//乘法
}p[maxn];
void push_up(ll o)
{
p[o].value=(p[lson].value+p[rson].value)%mod;
}
void push_down(ll o)
{
if(p[o].lazy||p[o].lazy1!=1)
{
p[lson].lazy=(p[lson].lazy*p[o].lazy1+p[o].lazy)%mod;
p[rson].lazy=(p[rson].lazy*p[o].lazy1+p[o].lazy)%mod;
p[lson].lazy1=(p[o].lazy1*p[lson].lazy1)%mod;
p[rson].lazy1=(p[o].lazy1*p[rson].lazy1)%mod;
p[lson].value=(p[lson].value*p[o].lazy1+p[o].lazy*p[lson].len)%mod;
p[rson].value=(p[rson].value*p[o].lazy1+p[o].lazy*p[rson].len)%mod;
p[o].lazy=0;
p[o].lazy1=1;
}
}
void build(ll o,ll l,ll r)
{
p[o].left=l;p[o].right=r;
p[o].len=r-l+1;
p[o].lazy=0;
p[o].lazy1=1;
if(l==r)
{
ll x;
scanf("%lld",&x);
p[o].value=x;
return ;
}
ll mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
push_up(o);
}
void update(ll o,ll l,ll r,ll v)//相加
{
if(p[o].left>=l&&p[o].right<=r)
{
p[o].lazy=(p[o].lazy+v)%mod;
p[o].value=(p[o].value+v*p[o].len)%mod;
return ;
}
push_down(o);
ll mid=(p[o].left+p[o].right)>>1;
if(r<=mid)
update(lson,l,r,v);
else if(l>mid)
update(rson,l,r,v);
else
{
update(lson,l,mid,v);
update(rson,mid+1,r,v);
}
push_up(o);
}
void update1(ll o,ll l,ll r,ll v)//相乘
{
if(p[o].left>=l&&p[o].right<=r)
{
p[o].value=(p[o].value*v)%mod;
p[o].lazy=(p[o].lazy*v)%mod;
p[o].lazy1=(p[o].lazy1*v)%mod;
return ;
}
push_down(o);
ll mid=(p[o].left+p[o].right)>>1;
if(r<=mid)
update1(lson,l,r,v);
else if(l>mid)
update1(rson,l,r,v);
else
{
update1(lson,l,mid,v);
update1(rson,mid+1,r,v);
}
push_up(o);
}
ll query(ll o,ll l,ll r)
{
if(p[o].left>=l&&p[o].right<=r)
return p[o].value;
ll mid=(p[o].left+p[o].right)>>1;
push_down(o);
if(r<=mid)
return query(lson,l,r);
else if(l>mid)
return query(rson,l,r);
else
return query(lson,l,mid)+query(rson,mid+1,r);
}
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
scanf("%d%d%d",&n,&m,&mod);
build(1,1,n);
int _;
ll a,b,c;
while(m--)
{
scanf("%d",&_);
if(_==3)
{
scanf("%lld%lld",&a,&b);
printf("%lld\n",query(1,a,b)%mod);
}
else if(_==2)
{
scanf("%lld%lld%lld",&a,&b,&c);
update(1,a,b,c);
}
else if(_==1)
{
scanf("%lld%lld%lld",&a,&b,&c);
update1(1,a,b,c);
}
}
return 0;
}

洛谷 P3373:【模板】线段树 2(区间更新)的更多相关文章

  1. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  2. hdu 1556:Color the ball(线段树,区间更新,经典题)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. hdu 1698:Just a Hook(线段树,区间更新)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. UVA 12436-Rip Van Winkle's Code(线段树的区间更新)

    题意: long long data[250001]; void A( int st, int nd ) { for( int i = st; i \le nd; i++ ) data[i] = da ...

  5. hdu1698线段树的区间更新区间查询

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  6. HDU 1556 Color the ball(线段树:区间更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=1556 题意: N个气球,每次[a,b]之间的气球涂一次色,统计每个气球涂色的次数. 思路: 这道题目用树状数组和 ...

  7. zoj3686(线段树的区间更新)

    对线段树的区间更新有了初步的了解... A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a ...

  8. Color the ball (线段树的区间更新问题)

    N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但 ...

  9. ZOJ 2301 Color the Ball 线段树(区间更新+离散化)

    Color the Ball Time Limit: 2 Seconds      Memory Limit: 65536 KB There are infinite balls in a line ...

  10. 线段树_区间加乘(洛谷P3373模板)

    题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字 ...

随机推荐

  1. linux下find命令详解

    Linux中find常见用法示例 ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数 ...

  2. learning scala 数组和容器

    数组:可变的,可索引的,元素具有相同类型的数据集合 一维数组 scala> val intValueArr = new Array[Int](3)intValueArr: Array[Int] ...

  3. 【收集资料】OpenGL学习

    1.课本配套网站,有Sample Code和书中的图片等   http://math.ucsd.edu/~sbuss/MathCG/ 2.Visual C++的帮助系统可查阅基本OpenGL函数(不包 ...

  4. SpringBoot入门示例

    SpringBoot入门Demo SpringBoot可以说是Spring的简化版.配置简单.使用方便.主要有以下几种特点: 创建独立的Spring应用程序 嵌入的Tomcat,无需部署WAR文件 简 ...

  5. sqlalchemy tree 树形分类 无限极分类的管理。预排序树,左右值树。sqlalchemy-mptt

    简介: 无限极分类是一种比较常见的数据格式,生成组织结构,生成商品分类信息,权限管理当中的细节权限设置,都离不开无限极分类的管理. 常见的有链表式,即有一个Pid指向上级的ID,以此来设置结构.写的时 ...

  6. [Leetcode 55]跳格子JumpGame

    [题目] Given an array of non-negative integers, you are initially positioned at the first index of the ...

  7. C++基础知识:构造与析构

    1.构造函数的定义: C++中的类可以定义与类名相同的特殊成员函数这种与类名相同的成员函数叫做构造函数构造函数在定义时可以有参数,但是没有任何返回类型的声明 2.构造函数的调用: 一般情况下C++编译 ...

  8. spring boot 发邮件

    报错:  Mail server connection failed; nested exception is javax.mail.MessagingException: Could not con ...

  9. vim 使用和配置

    vim 启动的时候,默认加载用户目录下.vimrc的配置文件,如果不存在,则会加载系统配置文件/etc/vim/vimrc ~/.vimrc文件配置 #避免中文乱码set fileencodings= ...

  10. Linux文件系统命令 mkdir/rmdir

    命令名:mkdir 功能:创建一个文件夹,和touch的区别是,touch是创建一个文件,后面可以跟绝对路径和相对路径 eg: mkdir ren 命令名:rmdir 功能:删除一个文件夹