• [模板]洛谷T3373 线段树 模板2


    此题相对于模板一,加了个区间乘,于是在模板一的基础上需要多开个数组(记录乘法懒标记)、多写个函数(区间乘),还有要把懒标记下放函数做些修改。

    变量定义:

    sum[]:线段树节点对应区间的元素总和;

    addv[]:线段树节点对应区间的所有元素待加的值(懒标记),初值全部设为0;

    mulv[]:线段树节点对应区间的所有元素待乘的值(懒标记),初值全部设为1。

    过程说明:

    建树(Build):

    同模板一。。。

    懒标记下放(Push_down):

    原理解释:

    1.当对某区间执行加法操作时,由于加法优先级低,不会对乘法操作产生影响,故直接相加即可;

    2.当对某区间执行乘法操作时,由于乘法优先级高,会对之前的加法操作产生影响,故需要在相乘时不仅对sum和mulv相乘,也需要对addv相乘;

    3.由于上述原因,故需要先算乘法再算加法。

    细节实现:

    1.子树的sum、mulv、addv值分别乘上当前节点的mulv值;

    2.当前节点的mulv值还原,即置为1;

    3.子树的addv值加上当前节点的addv值;

    4.子树的sum值加上(子树包含元素数量*当前节点的addv值);

    5.当前节点的addv值还原,即置为0。

    特别说明:

    1.使用前判断,若当前节点的懒标记为空则不需执行此下放函数。虽然执行了也不会有影响,但浪费时间;

    2.为尽量节省时间,要将判断放在此函数外而不是函数内。

    区间加(Addall):

    同模板一。。。

    区间乘(Mulall):

    若当前节点完全包含在待更新区间内,则直接修改当前节点的mulv、addv、sum值即可(参考下放函数说明);

    否则执行与区间加类似的操作即可。

    区间查询(Query):

    同模板一。。。

    提示:不要忘记取模。。。

    代码如下:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<ctime>
      5 #include<cstdlib>
      6 #include<cmath>
      7 #include<algorithm>
      8 #include<string>
      9 #include<stack>
     10 #include<queue>
     11 #include<vector>
     12 #include<map>
     13 using namespace std;
     14 long long c[500010];
     15 long long p;
     16 struct sgt{
     17     long long sum[2000010];
     18     long long addv[2000010];
     19     long long mulv[2000010];
     20     void build(int o,int l,int r){
     21         addv[o]=0;
     22         mulv[o]=1;
     23         if(l==r)sum[o]=c[l];
     24         else{
     25             int mid=(l+r)>>1;
     26             int lson=o<<1;
     27             int rson=lson|1;
     28             build(lson,l,mid);
     29             build(rson,mid+1,r);
     30             sum[o]=(sum[lson]+sum[rson])%p;
     31         }
     32     }    
     33     void push_down(int o,int l,int r,int mid,int lson,int rson){
     34         mulv[lson]=(mulv[lson]*mulv[o])%p;
     35         mulv[rson]=(mulv[rson]*mulv[o])%p;
     36         addv[lson]=(addv[lson]*mulv[o])%p;
     37         addv[rson]=(addv[rson]*mulv[o])%p;
     38         sum[lson]=(sum[lson]*mulv[o])%p;
     39         sum[rson]=(sum[rson]*mulv[o])%p;
     40         mulv[o]=1;
     41         addv[lson]=(addv[lson]+addv[o])%p;
     42         addv[rson]=(addv[rson]+addv[o])%p;
     43         sum[lson]=(sum[lson]+(mid-l+1)*addv[o])%p;
     44         sum[rson]=(sum[rson]+(r-mid)*addv[o])%p;
     45         addv[o]=0;
     46     }
     47     void addall(int o,int l,int r,int a,int b,int x){
     48         if(l>=a && r<=b){
     49             addv[o]=(addv[o]+x)%p;
     50             sum[o]=(sum[o]+(r-l+1)*x)%p;
     51             return;
     52         }
     53         else{
     54             int mid=(l+r)>>1;
     55             int lson=o<<1;
     56             int rson=lson|1;
     57             if(mulv[o]!=1 || addv[o])push_down(o,l,r,mid,lson,rson);
     58             if(a<=mid)addall(lson,l,mid,a,b,x);
     59             if(b>mid)addall(rson,mid+1,r,a,b,x);
     60             sum[o]=(sum[lson]+sum[rson])%p;
     61         }
     62     }
     63     void mulall(int o,int l,int r,int a,int b,int x){
     64         if(l>=a && r<=b){
     65             mulv[o]=(mulv[o]*x)%p;
     66             addv[o]=(addv[o]*x)%p;
     67             sum[o]=(sum[o]*x)%p;
     68             return;
     69         }
     70         else{
     71             int mid=(l+r)>>1;
     72             int lson=o<<1;
     73             int rson=lson|1;
     74             if(mulv[o]!=1 || addv[o])push_down(o,l,r,mid,lson,rson);
     75             if(a<=mid)mulall(lson,l,mid,a,b,x);
     76             if(b>mid)mulall(rson,mid+1,r,a,b,x);
     77             sum[o]=(sum[lson]+sum[rson])%p;
     78         }
     79     }
     80     long long query(int o,int l,int r,int a,int b){
     81         if(l>=a && r<=b)return sum[o]%p;
     82         else{
     83             int mid=(l+r)>>1;
     84             int lson=o<<1;
     85             int rson=lson|1;
     86             long long ans=0;
     87             if(mulv[o]!=1 || addv[o])push_down(o,l,r,mid,lson,rson);
     88             if(a<=mid)ans+=query(lson,l,mid,a,b);
     89             if(b>mid)ans+=query(rson,mid+1,r,a,b);
     90             return ans%p;
     91         }
     92     }
     93 };
     94 sgt tree;
     95 int n,m,i,f;
     96 int x,y;
     97 long long k;
     98 int main(){
     99     scanf("%d%d%d",&n,&m,&p);
    100     for(i=1;i<=n;i++)scanf("%d",&c[i]);
    101     tree.build(1,1,n);
    102     for(i=1;i<=m;i++){
    103         scanf("%d",&f);
    104         switch(f){
    105             case 1:{
    106                 scanf("%d%d%d",&x,&y,&k);
    107                 tree.mulall(1,1,n,x,y,k);
    108                 break;
    109             }
    110             case 2:{
    111                 scanf("%d%d%d",&x,&y,&k);
    112                 tree.addall(1,1,n,x,y,k);
    113                 break;
    114             }
    115             case 3:{
    116                 scanf("%d%d",&x,&y);
    117                 printf("%lld
    ",tree.query(1,1,n,x,y));
    118                 break;
    119             }    
    120         }
    121     }
    122     return 0;
    123 }
  • 相关阅读:
    HTML学习笔记2
    HTML的学习笔记
    Unsupported major.minor version 51.0解决办法
    java出现The type java.lang.Object cannot be resolved. It is indirectly referenced.....解决办法
    切片
    switch语句
    if-else语句与for循环
    闭包函数
    函数
    常量
  • 原文地址:https://www.cnblogs.com/running-coder-wfh/p/6901471.html
Copyright © 2020-2023  润新知