洛谷 P3373:【模板】线段树 2(区间更新)
题目描述
如题,已知一个数列,你需要进行下面三种操作:
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(区间更新)的更多相关文章
- 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)
To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...
- hdu 1556:Color the ball(线段树,区间更新,经典题)
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- hdu 1698:Just a Hook(线段树,区间更新)
Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 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 ...
- hdu1698线段树的区间更新区间查询
Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 1556 Color the ball(线段树:区间更新)
http://acm.hdu.edu.cn/showproblem.php?pid=1556 题意: N个气球,每次[a,b]之间的气球涂一次色,统计每个气球涂色的次数. 思路: 这道题目用树状数组和 ...
- zoj3686(线段树的区间更新)
对线段树的区间更新有了初步的了解... A Simple Tree Problem Time Limit: 3 Seconds Memory Limit: 65536 KB Given a ...
- Color the ball (线段树的区间更新问题)
N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但 ...
- ZOJ 2301 Color the Ball 线段树(区间更新+离散化)
Color the Ball Time Limit: 2 Seconds Memory Limit: 65536 KB There are infinite balls in a line ...
- 线段树_区间加乘(洛谷P3373模板)
题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入格式: 第一行包含三个整数N.M.P,分别表示该数列数字 ...
随机推荐
- [x] 封装、继承,多态
那么多态的作用是什么呢,封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用. 而多态的目的则是为了接口重用.也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接 ...
- PSP0级记录2
上课 编写程序 课外资料 日总计 3.13 周一 ...
- 5.8 C++重载自增与自减操作符
参考:http://www.weixueyuan.net/view/6386.html 注意: 自增“++”与自减“--”都是一元操作符,其前置和后置两种形式都可以被重载. 前置 stopwatch ...
- bootstrapValidator常用验证规则总结
bootstrapValidator常用验证规则总结 一 .bootstrapValidator引入 在使用bootstrapValidator前我们需要引入bootstrap和bootstrapVa ...
- Java语法基础学习DaySeven
---恢复内容开始--- 一.包装类——Wrapper 1.定义:针对八种基本数据类型定义相应的引用类型——包装类(封装类) boolean——Boolean byte——Byte ...
- 18-10-16 IE 快捷键的组合方式
一般快捷键 F11打开/关闭全屏模式 TAB循环的选择地址栏,刷新键和当前标签页 CTRL+F在当前标签页查询字或短语 CTRL+N为当前标签页打开一个新窗口 CTRL+P打印当前标签页 CTRL+A ...
- this 指向问题, 三个例子
'use strict'; var a = 20; function foo () { var a = 1; var obj = { a: 10, c: this.a + 20, fn: functi ...
- ChinaCock界面控件介绍-CCSystemBar
Android 4.4之后谷歌提供了沉浸式全屏体验, 在沉浸式全屏模式下, 状态栏. 虚拟按键动态隐藏, 应用可以使用完整的屏幕空间, 按照 Google 的说法, 给用户一种 身临其境 的体验.而A ...
- kbmMWLog输出日志到控制台或指定Grid
刚看到有人在kbmMW News问,有没有简单的方法,输出日志到Console窗口或者一个实际的Grid? 作者对此做回复,大意是这样: 对于输出日志到一个Memo,使用TkbmMWStringsLo ...
- Python中列表、元组、集合、字典
Python 列表(List) 列表是最常用的Python数据类型: 列表中的数据项不需要具有相同的类型: 列表也叫做数组,定义时使用[]: 通过下标访问列表中的元素,下标从 0 开始计数 列表的增 ...