题目描述
现在给你一串数字,a1,a2,a3…an,你需要进行m次如下几种操作:
1 l r v,区间a[l]到a[r]的所有数字全部加v。
2 l r v,区间a[l]到a[r]的所有数字全部乘v。
3 l r,求区间a[l]到a[r]之间两两之间数字的乘积和(例如:2,3,4,5两两之间乘积和为 2*3+2*4+2*5+3*4+3*5+4*5)
现在给出你操作的顺序,按照要求操作或者输出。
输入描述:
第一行,一个数字T,表示有T组数据。
每组数据,第一行三个数值,n,m,p,表示有n个数字,有m个操作,p为模数,所有算术操作均要取模。
第二行,n个数字,表示初始序列
接下来m行,每行第一个数为操作方法opt,
若opt=1或者2,则后面跟着三个数l,r,v,若opt=3,则后面跟着两个数字l,r其含义如题所示
1≤T≤10,1≤n≤100000,1≤m≤200000,2≤p≤INT_MAX
保证所有输入均在int范围内,所有数字均为整数,其中p为素数,保证数据合法。
输出描述:
对于每次操作3,输出一行一个数字ans(mod p),表示答案。
示例1
输入
1 5 6 1000000007 0 0 0 0 0 1 1 5 1 3 1 5 2 2 4 2 2 3 3 2 3 1 3 3 1 1输出
10 14 0备注:
- #include<bits/stdc++.h>
- using namespace std;
- const int MAXN = 100005;
- long long mod;
- long long A[MAXN];
- struct tnode
- {
- long long sum[2], lazy[2];
- int l, r;
- };
- tnode operator + (const tnode &A, const tnode &B)
- {
- tnode C;
- C.l = A.l;
- C.r = B.r;
- C.lazy[0] = 1;
- C.lazy[1] = 0;
- C.sum[0] = A.sum[0] + B.sum[0];
- if (C.sum[0] >= mod)C.sum[0] -= mod;
- C.sum[1] = A.sum[1] + B.sum[1];
- if (C.sum[1] >= mod)C.sum[1] -= mod;
- C.sum[1] += A.sum[0] * B.sum[0] % mod;
- if (C.sum[1] >= mod)C.sum[1] -= mod;
- return C;
- }
- struct Segment_Tree
- {
- tnode t[4 * MAXN];
- void init_lazy(int root)
- {
- t[root].lazy[0] = 1;
- t[root].lazy[1] = 0;
- }
- void union_lazy(int fa, int ch)
- {
- long long temp[2];
- temp[0] = t[fa].lazy[0] * t[ch].lazy[0] % mod;
- temp[1] = ((t[fa].lazy[0] * t[ch].lazy[1] % mod) + t[fa].lazy[1]) % mod;
- t[ch].lazy[0] = temp[0];
- t[ch].lazy[1] = temp[1];
- }
- void cal_lazy(int root)
- {
- long long len = (t[root].r - t[root].l + 1) % mod;
- t[root].sum[1] = (len * (len - 1) / 2 % mod * t[root].lazy[1] % mod * t[root].lazy[1] % mod +
- t[root].lazy[0] * t[root].lazy[0] % mod * t[root].sum[1] % mod +
- t[root].lazy[0] * t[root].lazy[1] % mod * (len - 1) % mod * t[root].sum[0] % mod) % mod;
- t[root].sum[0] = (len * t[root].lazy[1] % mod +
- t[root].lazy[0] * t[root].sum[0] % mod) % mod;
- return;
- }
- void push_down(int root)
- {
- if (t[root].lazy[0] != 1 || t[root].lazy[1] != 0)
- {
- cal_lazy(root);
- if (t[root].l != t[root].r)
- {
- int ch = root << 1;
- union_lazy(root, ch);
- union_lazy(root, ch + 1);
- }
- init_lazy(root);
- }
- }
- void update (int root)
- {
- int ch = root << 1;
- push_down(ch);
- push_down(ch + 1);
- t[root] = t[ch] + t[ch + 1];
- }
- void build(int root, int l, int r)
- {
- t[root].l = l;
- t[root].r = r;
- init_lazy(root);
- if (l != r)
- {
- int mid = (l + r) >> 1;
- int ch = root << 1;
- build(ch, l, mid);
- build(ch + 1, mid + 1, r);
- update(root);
- }
- else
- {
- t[root].sum[0] = A[l] % mod;
- t[root].sum[1] = 0;
- }
- }
- void change(int root, int l, int r, long long delta, int op)
- {
- push_down(root);
- if (l == t[root].l && r == t[root].r)
- {
- t[root].lazy[op] = delta % mod;
- return;
- }
- int mid = (t[root].l + t[root].r) >> 1;
- int ch = root << 1;
- if (r <= mid)change(ch, l, r, delta, op);
- else if (l > mid)change(ch + 1, l, r, delta, op);
- else {change(ch, l, mid, delta, op); change(ch + 1, mid + 1, r, delta, op);}
- update(root);
- }
- tnode sum(int root, int l, int r)
- {
- push_down(root);
- if (t[root].l == l && t[root].r == r)
- {
- return t[root];
- }
- int mid = (t[root].l + t[root].r) >> 1;
- int ch = root << 1;
- if (r <= mid)return sum(ch, l, r);
- else if (l > mid)return sum(ch + 1, l, r);
- else return sum(ch, l, mid) + sum(ch + 1, mid + 1, r);
- }
- };
- Segment_Tree ST;
- int n, m, op, l, r, T;
- long long x;
- int main()
- {
- scanf("%d", &T);
- while (T--)
- {
- scanf("%d %d %lld", &n, &m , &mod);
- for (int i = 1; i <= n; ++i)
- {
- scanf("%lld", &A[i]);
- }
- ST.build(1, 1, n);
- for (int _ = 1; _ <= m; ++_)
- {
- scanf("%d %d %d", &op, &l, &r);
- if (op <= 2)
- {
- scanf("%lld", &x);
- ST.change(1, l, r, x, 2 - op);
- }
- else
- {
- printf("%lld\n", ST.sum(1, l, r).sum[1]);
- }
- }
- }
- return 0;
- }