题解 | #E线段树#
线段树
https://ac.nowcoder.com/acm/contest/19684/E
<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(); }