• 线段树——维护序列(两个懒标记的情况)


    传送门:维护序列

    思路:这道题和一个简单的整数问题那道题2相比只是在原本的假发懒标记的基础上加多了一个乘法的懒标记,但这里的懒标记是有优先级问题的当两个懒标记或多个懒标记堆积在一起的时候先乘再加和先加再乘的结果是不一样的。

    所以本题的唯一难点就是在如何处理懒标记上。

    解决:

    对于一个要标记的节点p,分为以下几种情况:

    在已经有一个加法懒标记和一个乘法懒标记的基础上加多一个乘法的懒标记

    对于区间内的每一个数x都有

    (x*mul+add)*mul1;

    可以转化为x*mul*mul1+add*mul 

    在已经有一个加法懒标记和一个乘法懒标记的基础上加多一个加法的懒标记

    (x*mul+add+add1) 这里add可以直接加上新的add1

    代码拿出来就是:

    1. void eva(tree &t,int add,int mul)
    2. {
    3. t.sum=((ll)t.sum*mul+(ll)(t.r-t.l+1)*add)%mod;
    4. t.mul=((ll)t.mul*mul)%mod;
    5. t.add=((ll)t.add*mul+add)%mod;
    6. }

    因为新懒标记不会同时到来,只能一个一个传递,所以上面的函数中的每一次调用add为0要么mul为1;

    所以这条式子起作用的时候mul是等于1的。

    t.add=((ll)t.add*mul+add)%mod;
    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. using namespace std;
    7. typedef long long ll;
    8. typedef pair<int,int> PII;
    9. const int N=1e5+10;
    10. struct tree
    11. {
    12. int l, r;
    13. ll sum,add,mul;
    14. }t[N<<2];
    15. ll a[N];
    16. int n,m,mod;
    17. void pushup(int p)
    18. {
    19. t[p].sum=(t[2*p].sum+t[2*p+1].sum)%mod;
    20. }
    21. void eva(tree &t,int add,int mul)
    22. {
    23. t.sum=((ll)t.sum*mul+(ll)(t.r-t.l+1)*add)%mod;
    24. t.mul=((ll)t.mul*mul)%mod;
    25. t.add=((ll)t.add*mul+add)%mod; //这里为什么是乘mul呢?
    26. }
    27. void pushdown(int p)
    28. {
    29. eva(t[p*2],t[p].add,t[p].mul);
    30. eva(t[p*2+1],t[p].add,t[p].mul);
    31. t[p].add=0;
    32. t[p].mul=1;
    33. }
    34. void build(int p,int l,int r)
    35. {
    36. t[p].l=l;
    37. t[p].r=r;
    38. t[p].mul=1;
    39. if(l==r) {t[p].sum=a[l];return ;}
    40. int mid=(l+r)/2;
    41. build(2*p,l,mid);
    42. build(2*p+1,mid+1,r);
    43. pushup(p);
    44. }
    45. void change (int p,int l,int r,int add,int mul)
    46. {
    47. if(l<=t[p].l&&t[p].r<=r)
    48. {
    49. eva(t[p],add,mul);
    50. return;
    51. }
    52. pushdown(p);
    53. int mid=(t[p].l+t[p].r)/2;
    54. if(l<=mid) change(2*p,l,r,add,mul);
    55. if(r>mid) change(2*p+1,l,r,add,mul);
    56. pushup(p);
    57. }
    58. ll ask(int p,int l,int r)
    59. {
    60. if(l<=t[p].l&&t[p].r<=r) return t[p].sum;
    61. pushdown(p);
    62. int mid=(t[p].r+t[p].l)>>1;
    63. ll sum=0;
    64. if(l<=mid) sum=ask(2*p,l,r);
    65. if(r>mid) sum=(sum+ask(2*p+1,l,r))%mod;
    66. return sum;
    67. }
    68. int main()
    69. {
    70. scanf("%d%d",&n,&mod);
    71. for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    72. build(1,1,n);
    73. scanf("%d",&m);
    74. while(m--)
    75. {
    76. int l,r,d,t;
    77. scanf("%d%d%d",&t,&l,&r);
    78. if(t==1)
    79. {
    80. scanf("%d",&d);
    81. change(1,l,r,0,d);
    82. }else if(t==2)
    83. {
    84. scanf("%d",&d);
    85. change(1,l,r,d,1);
    86. }else
    87. printf("%lld\n",ask(1,l,r));
    88. }
    89. return 0;
    90. }

  • 相关阅读:
    TinyRenderer学习笔记--Lesson 3、4
    Serverless 架构下的 AI 应用开发
    医院预约挂号系统-系统结构
    字符串的常用方法-增删改查、转换方法split
    Stable Diffusion 最新Ebsynth Utility脚本生成AI动画视频
    【无标题】
    万字长文详解HBase读写性能优化
    史上最简SLAM零基础解读(8) - g2o(图优化)→示例代码讲解
    网工知识角|华为网络工程师,华为、华三、思科设备三层交换机如何使用三层接口?命令敲起来
    Dijkstra算法不能解决负权边的问题
  • 原文地址:https://blog.csdn.net/m0_62327332/article/details/126935438