AHOI 2009 维护序列
洛谷 P2023 [AHOI2009]维护序列
题目描述
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。 有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式:
(1)把数列中的一段数全部乘一个值;
(2)把数列中的一段数全部加一个值;
(3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值。
输入格式
第一行两个整数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)。
同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。
输出格式
对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。
输入输出样例
输入 #1复制
输出 #1复制
说明/提示
【样例说明】
初始时数列为(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
Source: Ahoi 2009
题解:
线段树模板维护区间乘和区间加,查询区间和。
如果对于简单线段树不是很了解的同学可以翻看本蒟蒻的这篇博客:
但是简单线段树并没有给出区间乘法的维护方法...
但我们可以参照区间加法进行类比。区间加法需要维护一个延迟标记,区间乘法当然也需要,由于乘法就是一连串的加法,所以我们在下传延迟标记的时候不仅需要下传乘法标记给线段树数组和子节点的乘法标记数组,还要把乘法标记下传给加法标记数组。也就是说:
线段树维护区间乘法的步骤为:
线段树数组乘标记,自己乘标记,加法数组乘标记。
加法的直接上简单线段树的板子即可。
注意,先乘后加!
代码:
#include<cstdio>
#define int long long
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
const int maxn=1e5+10;
int n,m,mod;
int a[maxn];
int tree[maxn<<2],lazy[maxn<<2],lazy2[maxn<<2];
void build(int pos,int l,int r)
{
int mid=(l+r)>>1;
if(l==r)
{
tree[pos]=a[l];
return;
}
build(lson,l,mid);
build(rson,mid+1,r);
tree[pos]=(tree[lson]+tree[rson])%mod;
}
void mark(int pos,int l,int r,int k,int flag)
{
if(flag)
{
tree[pos]=(tree[pos]*k)%mod;
lazy2[pos]=(lazy2[pos]*k)%mod;
lazy[pos]=(lazy[pos]*k)%mod;
}
else
{
tree[pos]=(tree[pos]+(r-l+1)*k)%mod;
lazy2[pos]=(lazy2[pos]+k)%mod;
}
}
void pushdown(int pos,int l,int r)
{
int mid=(l+r)>>1;
mark(lson,l,mid,lazy[pos],1);
mark(rson,mid+1,r,lazy[pos],1);
mark(lson,l,mid,lazy2[pos],0);
mark(rson,mid+1,r,lazy2[pos],0);
lazy2[pos]=0,lazy[pos]=1;
}
void update(int pos,int l,int r,int x,int y,int k,int flag)
{
int mid=(l+r)>>1;
if(x<=l && r<=y)
{
if(flag)
mark(pos,l,r,k,flag);
else
mark(pos,l,r,k,flag);
return;
}
pushdown(pos,l,r);
if(x<=mid)
update(lson,l,mid,x,y,k,flag);
if(y>mid)
update(rson,mid+1,r,x,y,k,flag);
tree[pos]=(tree[lson]+tree[rson])%mod;
}
int query(int pos,int l,int r,int x,int y)
{
int ret=0;
int mid=(l+r)>>1;
if(x<=l && r<=y)
return tree[pos]%mod;
pushdown(pos,l,r);
if(x<=mid)
ret=(ret+query(lson,l,mid,x,y))%mod;
if(y>mid)
ret=(ret+query(rson,mid+1,r,x,y))%mod;
return ret%mod;
}
signed main()
{
for(int i=1;i<=maxn<<2;i++)
lazy[i]=1,lazy2[i]=0;
scanf("%lld%lld",&n,&mod);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
scanf("%lld",&m);
for(int i=1;i<=m;i++)
{
int opt,x,y,k;
scanf("%lld",&opt);
if(opt==1)
{
scanf("%lld%lld%lld",&x,&y,&k);
update(1,1,n,x,y,k,1);
}
else if(opt==2)
{
scanf("%lld%lld%lld",&x,&y,&k);
update(1,1,n,x,y,k,0);
}
else
{
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(1,1,n,x,y));
}
}
return 0;
}
AHOI 2009 维护序列的更多相关文章
- [AHOI 2009] 维护序列(线段树模板题)
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小 ...
- [洛谷P2023] [AHOI2009]维护序列
洛谷题目链接:[AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列 ...
- 洛谷 P2023 [AHOI2009]维护序列
P2023 [AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中 ...
- 洛谷 P2023 [AHOI2009]维护序列 题解
P2023 [AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列中 ...
- [P2023][AHOI2009]维护序列(线段树)
题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一 ...
- [AHOI2009]维护序列 (线段树)
题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一 ...
- 洛谷 P2023 BZOJ 1798 [AHOI2009]维护序列
题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一 ...
- BZOJ1798: [Ahoi2009]Seq 维护序列seq[线段树]
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 5504 Solved: 1937[Submit ...
- bzoj 维护序列seq(双标记线段树)
Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 4184 Solved: 1518[Submit][Status][Discus ...
随机推荐
- Flask 模板语言,装饰器
Jinja2模板语言 # -*- coding: utf-8 -*- from flask import Flask, render_template, request, redirect, ...
- HTML入门(转义字符、行内样式和块级元素、定位、锚点、跑马灯标签、图片标签、表格标签的讲解)
一.转义字符由特殊字符包裹的文本 会当做标签去解析 对应不换行空格 对应全角空格 em是字体排印学的计量单位,相当于当前指定的点数.其占据的宽度正好是1个中文宽度,而且基本上不受字体影响.<对应 ...
- 使用ul和li进行图片的布局
使用ul和li进行浮动布局(自适应) 1 图片上下两排: 首先盒子的宽度要给100% ul包裹一个div,首先量好盒子的宽和高,并进行设置, margin 0 auto 盒子居中显示 每个li向左浮动 ...
- English:Day-to-day 1104
\ ------------------------------ editor by enomothem ------------------------------ It snowed throug ...
- JS Navigator
JS Navigator window.navigator 对象包含有关访问者浏览器的信息. Window Navigator window.navigator 对象在编写时可不使用 window 这 ...
- oracle 根据时间戳查询date类型sql
话不多说上sql: select to_char(1574837126879/(1000*60*60*24)+to_date('1970-01-01 08:00:00','YYYY-MM-DD HH2 ...
- pycharm添加快捷键:
- SQL Server 索引分析开关
set statistics io onset statistics profile on
- 【洛谷5644】[PKUWC2018] 猎人杀(容斥+生成函数+分治NTT)
点此看题面 大致题意: 有\(n\)个人相互开枪,每个人有一个仇恨度\(a_i\),每个人死后会开枪再打死另一个还活着的人,且第一枪由你打响.设当前剩余人仇恨度总和为\(k\),则每个人被打中的概率为 ...
- Java实现网络聊天中使用的socket API与Linux socket API之间的关系
尝试着用Java编写一个网络聊天程序,发现总不如网上写的好,所以就直接引用了网上大神的优秀代码.代码如下: package project1; import java.awt.*; import ja ...