<E-线段树>这题一开始看别人的代码,基本都是暴力维护,一个维护区间的和,一个维护的是答案要给出的,但是仔细思考之后并没有这么的麻烦
经过把玩样例和理解题意可得我们要求的ans即为上述的式子,通过基础和式变换可转化成
也就是区间和的平方减去区间平方和乘以二分之一,这应该就是此题的正解,用线段树维护区间和以及区间平方和即可,可以直接把上一题代码搬过来加取模就行,不过注意取模很ex,我因为取模被卡了好久好久qwq
下面给出代码!!!
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <math.h>
#include <map>
#include <set>
using namespace std;
#define int long long
#define endl '\n'
const int maxn = 100005;
const int maxm = maxn << 1;
int p;
#define lson node << 1
#define rson node << 1 | 1
struct node{
int val,pf,add,mul;
}t[maxn << 2];
int n,m;
int a[maxn];
void pushup(int node){
t[node].val = (t[lson].val + t[rson].val) % p;
t[node].pf = (t[lson].pf + t[rson].pf) % p;
}
void spread(int l,int r,int node){
int &k = t[node].mul;
t[lson].mul = t[lson].mul * k % p;
t[rson].mul = t[rson].mul * k % p;
t[lson].add = t[lson].add * k % p;
t[rson].add = t[rson].add * k % p;
t[lson].val = t[lson].val * k % p;
t[rson].val = t[rson].val * k % p;
t[lson].pf = t[lson].pf * k % p * k % p;
t[rson].pf = t[rson].pf * k % p * k % p;
k = 1;
int mid = l + r >> 1;
int &x = t[node].add;
t[lson].add = (t[lson].add + x) % p;
t[rson].add = (t[rson].add + x) % p;
t[lson].pf = (t[lson].pf + 2 * t[lson].val % p * x % p + x * x % p * (mid - l + 1) % p) % p;
t[rson].pf = (t[rson].pf + 2 * t[rson].val % p * x % p + x * x % p * (r - mid) % p) % p;
t[lson].val = (t[lson].val + (mid - l + 1) * x % p) % p;
t[rson].val = (t[rson].val + (r - mid) * x % p) % p;
x = 0;
}
void build(int l,int r,int node){
t[node].mul = 1;
t[node].add = 0;
if (l == r) {
t[node].val = a[l] % p;
t[node].pf = a[l] * a[l] % p;
return;
}
int mid = l + r >> 1;
build(l,mid,lson);
build(mid+1,r,rson);
pushup(node);
}
void add(int l,int r,int x,int y,int node,int k){
if (x <= l && r <= y){
t[node].pf = (t[node].pf + 2 * t[node].val % p * k % p + k * k % p * (r - l + 1)) % p;
t[node].val = (t[node].val + k * (r - l + 1) % p) % p;
t[node].add = (t[node].add + k) % p;
return;
}
spread(l,r,node);
int mid = l + r >> 1;
if (x <= mid) add(l,mid,x,y,lson,k);
if (y > mid) add(mid+1,r,x,y,rson,k);
pushup(node);
}
void mul(int l,int r,int x,int y,int node,int k){
if (x <= l && r <= y){
t[node].val = t[node].val * k % p;
t[node].pf = t[node].pf * k % p * k % p;
t[node].add = t[node].add * k % p;
t[node].mul = t[node].mul * k % p;
return;
}
spread(l,r,node);
int mid = l + r >> 1;
if (x <= mid) mul(l,mid,x,y,lson,k);
if (y > mid) mul(mid+1,r,x,y,rson,k);
pushup(node);
}
int queryval(int l,int r,int x,int y,int node){
if (x <= l && r <= y){
return t[node].val;
}
spread(l,r,node);
int mid = l + r >> 1;
int ans = 0;
if (x <= mid) ans = (ans + queryval(l,mid,x,y,lson)) % p;
if (y > mid) ans = (ans + queryval(mid+1,r,x,y,rson)) % p;
return ans % p;
}
int querypf(int l,int r,int x,int y,int node){
if (x <= l && r <= y){
return t[node].pf;
}
spread(l,r,node);
int mid = l + r >> 1;
int ans = 0;
if (x <= mid) ans += querypf(l,mid,x,y,lson);
if (y > mid) ans += querypf(mid+1,r,x,y,rson);
return ans % p;
}
int quick(int n,int q){
int ans = 1;
while (q){
if (q & 1) ans = ans * n % p;
q >>= 1;
n = n * n % p;
}
return ans;
}
void solve(){
cin >> n >> m >> p;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
build(1,n,1);
while (m --){
int op,x,l,r;
cin >> op >> l >> r ;
if (op == 3){
int val = queryval(1,n,l,r,1);
int pf = querypf(1,n,l,r,1);
cout << (val * val % p - pf + p) % p * quick(2,p - 2) % p << endl;
}
if (op == 2){
cin >> x;
mul(1,n,l,r,1,x);
}
if (op == 1){
cin >> x;
add(1,n,l,r,1,x);
}
}
}
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int t;
cin >> t;
while (t--) solve();
}
京公网安备 11010502036488号