LOJ #6283. 数列分块入门 7-分块(区间乘法、区间加法、单点查询)
题目描述
给出一个长为 nn 的数列,以及 nn 个操作,操作涉及区间乘法,区间加法,单点询问。
输入格式
第一行输入一个数字 nn。
第二行输入 nn 个数字,第 ii 个数字为 a_iai,以空格隔开。
接下来输入 nn 行询问,每行输入四个数字 \mathrm{opt}opt、ll、rr、cc,以空格隔开。
若 \mathrm{opt} = 0opt=0,表示将位于 [l, r][l,r] 的之间的数字都加 cc。
若 \mathrm{opt} = 1opt=1,表示将位于 [l, r][l,r] 的之间的数字都乘 cc。
若 \mathrm{opt} = 2opt=2,表示询问 a_rar 的值 \mathop{\mathrm{mod}} 10007mod10007(ll 和 cc 忽略)。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
7
1 2 2 3 9 3 2
0 1 3 1
2 1 3 1
1 1 4 4
0 1 7 2
1 2 6 4
1 1 6 5
2 2 6 4
样例输出
3
100
数据范围与提示
对于 100\%100% 的数据,1 \leq n \leq 100000, -2^{31} \leq \mathrm{others}1≤n≤100000,−231≤others、\mathrm{ans} \leq 2^{31}-1ans≤231−1。
这道题要开比1e5大,要不然过不去,真实测试。。。
代码:
//#6283. 数列分块入门 7-区间乘法,区间加法,单点查询-要开1e6,mdzz
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+; int n,m;
int a[maxn],add[maxn],mul[maxn],pos[maxn];
const int mod=; void update_add(int l,int r,int c)
{
if(pos[l]==pos[r]){
for(int i=(pos[l]-)*m+;i<=pos[l]*m;i++){
a[i]=(a[i]*mul[pos[l]]%mod+add[pos[l]]+mod)%mod;
}
for(int i=l;i<=r;i++)
a[i]=(a[i]+c+mod)%mod;
mul[pos[l]]=;add[pos[l]]=;
}
else{
for(int i=(pos[l]-)*m+;i<=pos[l]*m;i++){
a[i]=(a[i]*mul[pos[l]]%mod+add[pos[l]]+mod)%mod;
}
for(int i=l;i<=pos[l]*m;i++)
a[i]=(a[i]+c+mod)%mod;
mul[pos[l]]=;add[pos[l]]=;
for(int i=pos[l]+;i<pos[r];i++){
add[i]=(add[i]+c+mod)%mod;
}
for(int i=(pos[r]-)*m+;i<=min(pos[r]*m,n);i++){
a[i]=(a[i]*mul[pos[r]]%mod+add[pos[r]]+mod)%mod;
}
for(int i=(pos[r]-)*m+;i<=r;i++)
a[i]=(a[i]+c+mod)%mod;
mul[pos[r]]=;add[pos[r]]=;
}
} void update_mul(int l,int r,int c)
{
if(pos[l]==pos[r]){
for(int i=(pos[l]-)*m+;i<=pos[l]*m;i++){
a[i]=(a[i]*mul[pos[l]]%mod+add[pos[l]]+mod)%mod;
}
for(int i=l;i<=r;i++)
a[i]=(a[i]*c+mod)%mod;
mul[pos[l]]=;add[pos[l]]=;
}
else{
for(int i=(pos[l]-)*m+;i<=pos[l]*m;i++){
a[i]=(a[i]*mul[pos[l]]%mod+add[pos[l]]+mod)%mod;
}
for(int i=l;i<=pos[l]*m;i++)
a[i]=(a[i]*c+mod)%mod;
mul[pos[l]]=;add[pos[l]]=;
for(int i=pos[l]+;i<pos[r];i++){
add[i]=(add[i]*c+mod)%mod;
mul[i]=(mul[i]*c+mod)%mod;
}
for(int i=(pos[r]-)*m+;i<=min(pos[r]*m,n);i++){
a[i]=(a[i]*mul[pos[r]]%mod+add[pos[r]]+mod)%mod;
}
for(int i=(pos[r]-)*m+;i<=r;i++)
a[i]=(a[i]*c+mod)%mod;
mul[pos[r]]=;add[pos[r]]=;
}
} int main()
{
scanf("%d",&n);
m=sqrt(n);
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
a[i]%=mod;
pos[i]=(i-)/m+;
mul[pos[i]]=;
add[pos[i]]=;
}
for(int i=;i<=n;i++){
int op,l,r,c;
scanf("%d%d%d%d",&op,&l,&r,&c);
c%=mod;
if(op==){
update_add(l,r,c);
}
else if(op==){
update_mul(l,r,c);
}
else if(op==){
printf("%d\n",(a[r]*mul[pos[r]]+add[pos[r]])%mod);
}
}
} /*
10
1 3 4 2 5 7 11 3 5 1
0 1 5 1
1 1 7 2
2 3 9 1
0 4 8 1
1 1 5 2
1 3 5 2
2 5 7 1
1 3 5 2
2 2 3 2
2 3 4 5 5
23
80
56
*/
LOJ #6283. 数列分块入门 7-分块(区间乘法、区间加法、单点查询)的更多相关文章
- bzoj 1798: [Ahoi2009]Seq 维护序列seq 线段树 区间乘法区间加法 区间求和
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeO ...
- LOJ#6283. 数列分块入门 7
对于每个区间先乘在加,如果我修改的是部分的块,我就需要把现这个块的add和mul标记全部放下去,然后再更新. #include<map> #include<set> #incl ...
- LOJ.6281.数列分块入门5(分块 区间开方)
题目链接 int内的数(也不非得是int)最多开方4.5次就变成1了,所以还不是1就暴力,是1就直接跳过. #include <cmath> #include <cstdio> ...
- LibreOJ 6280 数列分块入门 4(分块区间加区间求和)
题解:分块的区间求和比起线段树来说实在是太好写了(当然,复杂度也高)但这也是没办法的事情嘛.总之50000的数据跑了75ms左右还是挺优越的. 比起单点询问来说,区间询问和也没有复杂多少,多开一个su ...
- LOJ.6284.数列分块入门8(分块)
题目链接 \(Description\) 给出一个长为n的数列,以及n个操作,操作涉及区间询问等于一个数c的元素,并将这个区间的所有元素改为c. \(Solution\) 模拟一些数据可以发现,询问后 ...
- LibreOJ 6281 数列分块入门 5(分块区间开方区间求和)
题解:区间开方emmm,这马上让我想起了当时写线段树的时候,很显然,对于一个在2^31次方以内的数,开方7-8次就差不多变成一了,所以我们对于每次开方,如果块中的所有数都为一了,那么开方也没有必要了. ...
- LibreOJ 6277 数列分块入门 1(分块)
题解:感谢hzwer学长和loj让本蒟蒻能够找到如此合适的入门题做. 这是一道非常标准的分块模板题,本来用打标记的线段树不知道要写多少行,但是分块只有这么几行,极其高妙. 代码如下: #include ...
- [Libre 6281] 数列分块入门 5 (分块)
水一道入门分块qwq 题面:传送门 开方基本暴力.. 如果某一个区间全部都开成1或0就打上标记全部跳过就行了 因为一个数开上个四五六次就是1了所以复杂度能过233~ code: //By Menteu ...
- LibreOJ 6278 数列分块入门 2(分块)
题解:非常高妙的分块,每个块对应一个桶,桶内元素全部sort过,加值时,对于零散块O(sqrt(n))暴力修改,然后暴力重构桶.对于大块直接整块加.查询时对于非完整块O(sqrt(n))暴力遍历.对 ...
随机推荐
- main函数的传参与返回
1.谁给main函数传参(1)调用main函数所在的程序的它的父进程给main函数传参,并且接收main的返回值.2.为什么需要给main函数传参(1)首先,main函数不传参是可以的,也就是说父进程 ...
- Spring Boot应用中的异常处理
在普通的单线程程序中,捕获异常只需要通过try ... catch ... finally ...代码块就可以了.那么,在并发情况下,比如在父线程中启动了子线程,如何正确捕获子线程中的异常,从而进行相 ...
- bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description ...
- LightOJ 1269 - Consecutive Sum Trie树
题意:给出一串序列,求区间连续异或值的最大和最小. 思路:如果不是出在专题里,想不到可以用字典树做.先求前缀异或值,转为二进制,加入Trie树中,如果要求最大,就是尽可能走和当前位数字相反的,这样异或 ...
- redis linux下的开机启动
redis linux下的环境搭建 http://www.cnblogs.com/zsg88/p/8321644.html 安装完redis-4.0.1后设置linux开机自启动. 1.在re ...
- android:process结合activity启动模式的一次实践
会有这样的场景,一个应用崩溃了,而导致的该应用崩溃的原因是,该应用占用的内存大小超过了系统分配给它的最大堆大小.对象的分配,是发生在堆(heap)上面的,系统分配给每个应用的最大堆大小是固定的. 假设 ...
- bzoj 1058 bst
因为是数列的维护,所以我们可以考虑用splay来维护,每次在x插入的时候就在x+1前面插入就行了,然后用bst来维护两问的答案,但是应该会tle.我们来考虑这个问题的性质,首先因为这个数列没有删除操作 ...
- js删除数组中重复的元素
1.方法一 将数组逐个搬到另一个数组中,当遇到重复元素时,不移动,若元素不重复则移动到新数组中 function unique(arr){ var len = arr.length; var resu ...
- promise 如何知道所有的回调都执行完了?
var fs = require('fs'); /** * @return {object} Promise */ function doThing(fileName) { // ... // con ...
- Linux汇编教程04:寻址方式
这一节,我们主要来讨论寻址方式,这一点十分重要. 我们上一节有稍微提了一下,内存地址引用的通用格式: 地址或偏移(%基址寄存器, %索引寄存器, 比例因子 ) 结果地址 = 地址或偏移 + %基址寄存 ...