题意:区间加,区间乘,单点询问
思路:假设一个点为a,那么他可以表示为m * a + sum,所以区间加就变为m * a + sum + sum2,区间乘变为m * m2 * a + sum * m2。左右两边的块要先puhs down。
代码:
#include<cmath> #include<set> #include<map> #include<queue> #include<cstdio> #include<vector> #include<cstring> #include <iostream> #include<algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 1e5 + 10; const int M = maxn * 30; const ull seed = 131; const int INF = 0x3f3f3f3f; const int MOD = 1e4 + 7; struct Block{ int l, r; }b[maxn]; int a[maxn], sum[maxn], mult[maxn], belong[maxn]; int n, block; void down(int bl){ for(int i = b[bl].l; i <= b[bl].r; i++){ a[i] = (a[i] * mult[bl] + sum[bl]) % MOD; } mult[bl] = 1; sum[bl] = 0; } void add(int l, int r, int c){ int bl = belong[l], br = belong[r]; if(bl == br){ down(bl); for(int i = l; i <= r; i++){ a[i] = (a[i] + c) % MOD; } } else{ down(bl); for(int i = l; i <= b[bl].r; i++){ a[i] = (a[i] + c) % MOD; } for(int i = bl + 1; i <= br - 1; i++){ sum[i] = (sum[i] + c) % MOD; } down(br); for(int i = b[br].l; i <= r; i++){ a[i] = (a[i] + c) % MOD; } } } void mul(int l, int r, int c){ int bl = belong[l], br = belong[r]; if(bl == br){ down(bl); for(int i = l; i <= r; i++){ a[i] = (a[i] * c) % MOD; } } else{ down(bl); for(int i = l; i <= b[bl].r; i++){ a[i] = (a[i] * c) % MOD; } for(int i = bl + 1; i <= br - 1; i++){ mult[i] = (mult[i] * c) % MOD; sum[i] = (sum[i] * c) % MOD; } down(br); for(int i = b[br].l; i <= r; i++){ a[i] = (a[i] * c) % MOD; } } } int main(){ scanf("%d", &n); for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); } block = sqrt(n); for(int i = 1; i <= n; i++){ belong[i] = (i - 1) / block + 1; } for(int i = 1; i <= belong[n]; i++){ b[i].l = (i - 1) * block + 1; b[i].r = min(n, b[i].l + block - 1); sum[i] = 0, mult[i] = 1; } for(int i = 1; i <= n; i++){ int o, l, r; int c; scanf("%d%d%d%d", &o, &l, &r, &c); if(o == 0){ add(l, r, c); } else if(o == 1){ mul(l, r, c); } else{ int ans = (a[r] * mult[belong[r]] % MOD + sum[belong[r]]) % MOD; printf("%d ", ans); } } return 0; }