LOJ #6283. 数列分块入门 7-分块(区间乘法、区间加法、单点查询)

时间:2023-03-10 04:08:20
LOJ #6283. 数列分块入门 7-分块(区间乘法、区间加法、单点查询)
内存限制:256 MiB时间限制:500 ms标准输入输出
题目类型:传统评测方式:文本比较
上传者: hzwer

题目描述

给出一个长为 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
*/