整理的算法模板合集: ACM模板
题目传送门
同线段树,维护的时候先乘再加。
要时刻注意懒惰标记的下标是块的编号!!!
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 500007, M = 1000007, INF = 0x3f3f3f3f;
const double inf = 1e100;
const double eps = 1e-8;
const int mod = 10007;
//先乘再加
//乘的时候加也要乘
int n, m;
int atag[N];
int mtag[N];
int block, bi[N];
int v[N];
int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){if(ch == '-')f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
void reset_block(int x)//单块重置
{
for(int i = (x - 1) * block + 1; i <= min(n, x * block); ++ i){//注意这里有可能超过n
v[i] = (v[i] * mtag[x] + atag[x]) % mod;
}
atag[x] = 0;
mtag[x] = 1;
}
void solve(int op, int a, int b, int c)
{
reset_block(bi[a]);
for(int i = a; i <= min(bi[a] * block, b); ++ i){
if(op == 0)v[i] = (v[i] + c) % mod;
else {
v[i] = (v[i] * c) % mod;
}
}
if(bi[a] != bi[b]){
reset_block(bi[b]);
for(int i = (bi[b] - 1) * block + 1; i <= b; ++ i){
if(op == 0)v[i] = (v[i] + c) % mod;
else {
v[i] = (v[i] * c) % mod;
}
}
}
for(int i = bi[a] + 1; i <= bi[b] - 1; ++ i){
if(op == 0)atag[i] = (atag[i] + c) % mod;
else {
atag[i] = (atag[i] * c) % mod;
mtag[i] = (mtag[i] * c) % mod;
}
}
}
int query(int a, int b, int c)
{
return v[b] * mtag[bi[b]] + atag[bi[b]] % mod;
}
int main()
{
scanf("%d", &n);
block = sqrt(n);
for(int i = 1; i <= n; ++ i)
scanf("%d", &v[i]);
for(int i = 1; i <= n; ++ i){
bi[i] = (i - 1) / block + 1;
}
for(int i = 1 ; i <= bi[n]; ++ i){
atag[i] = 0;
mtag[i] = 1;
}
for(int i = 1; i <= n; ++ i){
int op = read(), a = read(), b = read(), c = read();
if(op == 2){
printf("%d\n", (v[b] * mtag[bi[b]] + atag[bi[b]]) % mod);
}
else solve(op, a, b, c);
}
return 0;
}