• 线段树板子4



     

    题目描述

    现在给你一串数字,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

    备注:

     
    
    1. #include<bits/stdc++.h>
    2. using namespace std;
    3. const int MAXN = 100005;
    4. long long mod;
    5. long long A[MAXN];
    6. struct tnode
    7. {
    8. long long sum[2], lazy[2];
    9. int l, r;
    10. };
    11. tnode operator + (const tnode &A, const tnode &B)
    12. {
    13. tnode C;
    14. C.l = A.l;
    15. C.r = B.r;
    16. C.lazy[0] = 1;
    17. C.lazy[1] = 0;
    18. C.sum[0] = A.sum[0] + B.sum[0];
    19. if (C.sum[0] >= mod)C.sum[0] -= mod;
    20. C.sum[1] = A.sum[1] + B.sum[1];
    21. if (C.sum[1] >= mod)C.sum[1] -= mod;
    22. C.sum[1] += A.sum[0] * B.sum[0] % mod;
    23. if (C.sum[1] >= mod)C.sum[1] -= mod;
    24. return C;
    25. }
    26. struct Segment_Tree
    27. {
    28. tnode t[4 * MAXN];
    29. void init_lazy(int root)
    30. {
    31. t[root].lazy[0] = 1;
    32. t[root].lazy[1] = 0;
    33. }
    34. void union_lazy(int fa, int ch)
    35. {
    36. long long temp[2];
    37. temp[0] = t[fa].lazy[0] * t[ch].lazy[0] % mod;
    38. temp[1] = ((t[fa].lazy[0] * t[ch].lazy[1] % mod) + t[fa].lazy[1]) % mod;
    39. t[ch].lazy[0] = temp[0];
    40. t[ch].lazy[1] = temp[1];
    41. }
    42. void cal_lazy(int root)
    43. {
    44. long long len = (t[root].r - t[root].l + 1) % mod;
    45. t[root].sum[1] = (len * (len - 1) / 2 % mod * t[root].lazy[1] % mod * t[root].lazy[1] % mod +
    46. t[root].lazy[0] * t[root].lazy[0] % mod * t[root].sum[1] % mod +
    47. t[root].lazy[0] * t[root].lazy[1] % mod * (len - 1) % mod * t[root].sum[0] % mod) % mod;
    48. t[root].sum[0] = (len * t[root].lazy[1] % mod +
    49. t[root].lazy[0] * t[root].sum[0] % mod) % mod;
    50. return;
    51. }
    52. void push_down(int root)
    53. {
    54. if (t[root].lazy[0] != 1 || t[root].lazy[1] != 0)
    55. {
    56. cal_lazy(root);
    57. if (t[root].l != t[root].r)
    58. {
    59. int ch = root << 1;
    60. union_lazy(root, ch);
    61. union_lazy(root, ch + 1);
    62. }
    63. init_lazy(root);
    64. }
    65. }
    66. void update (int root)
    67. {
    68. int ch = root << 1;
    69. push_down(ch);
    70. push_down(ch + 1);
    71. t[root] = t[ch] + t[ch + 1];
    72. }
    73. void build(int root, int l, int r)
    74. {
    75. t[root].l = l;
    76. t[root].r = r;
    77. init_lazy(root);
    78. if (l != r)
    79. {
    80. int mid = (l + r) >> 1;
    81. int ch = root << 1;
    82. build(ch, l, mid);
    83. build(ch + 1, mid + 1, r);
    84. update(root);
    85. }
    86. else
    87. {
    88. t[root].sum[0] = A[l] % mod;
    89. t[root].sum[1] = 0;
    90. }
    91. }
    92. void change(int root, int l, int r, long long delta, int op)
    93. {
    94. push_down(root);
    95. if (l == t[root].l && r == t[root].r)
    96. {
    97. t[root].lazy[op] = delta % mod;
    98. return;
    99. }
    100. int mid = (t[root].l + t[root].r) >> 1;
    101. int ch = root << 1;
    102. if (r <= mid)change(ch, l, r, delta, op);
    103. else if (l > mid)change(ch + 1, l, r, delta, op);
    104. else {change(ch, l, mid, delta, op); change(ch + 1, mid + 1, r, delta, op);}
    105. update(root);
    106. }
    107. tnode sum(int root, int l, int r)
    108. {
    109. push_down(root);
    110. if (t[root].l == l && t[root].r == r)
    111. {
    112. return t[root];
    113. }
    114. int mid = (t[root].l + t[root].r) >> 1;
    115. int ch = root << 1;
    116. if (r <= mid)return sum(ch, l, r);
    117. else if (l > mid)return sum(ch + 1, l, r);
    118. else return sum(ch, l, mid) + sum(ch + 1, mid + 1, r);
    119. }
    120. };
    121. Segment_Tree ST;
    122. int n, m, op, l, r, T;
    123. long long x;
    124. int main()
    125. {
    126. scanf("%d", &T);
    127. while (T--)
    128. {
    129. scanf("%d %d %lld", &n, &m , &mod);
    130. for (int i = 1; i <= n; ++i)
    131. {
    132. scanf("%lld", &A[i]);
    133. }
    134. ST.build(1, 1, n);
    135. for (int _ = 1; _ <= m; ++_)
    136. {
    137. scanf("%d %d %d", &op, &l, &r);
    138. if (op <= 2)
    139. {
    140. scanf("%lld", &x);
    141. ST.change(1, l, r, x, 2 - op);
    142. }
    143. else
    144. {
    145. printf("%lld\n", ST.sum(1, l, r).sum[1]);
    146. }
    147. }
    148. }
    149. return 0;
    150. }

     

  • 相关阅读:
    Arthas-好用的代码热更新&服务监控诊断工具
    Flutter dio上传大文件时应用内存不足问题解决
    【高性能计算】OneAPI入门
    我的学习方法论
    纺织工厂数字孪生3D可视化管理平台,推动纺织产业数字化转型
    12、分页插件
    键值对RDD数据自定义分区_大数据培训
    Codeforces Global Round 21 C D E
    vue render 函数自定义事件
    [附源码]计算机毕业设计springbootSwitch交流平台
  • 原文地址:https://blog.csdn.net/m0_61949623/article/details/126551258