首页 > 其他分享 >P3373 【模板】线段树 2(区间乘+加操作,先乘后加原则)

P3373 【模板】线段树 2(区间乘+加操作,先乘后加原则)

时间:2024-07-19 17:33:28浏览次数:4  
标签:先乘 后加 tree len int add op P3373 Mod

题目来源:https://www.luogu.com.cn/problem/P3373
//
题意:对区间[l,r]可以乘法,加法操作,查询和操作。
//
思路:既有乘法又有加法,肯定是要有两个标记。纯加法和纯乘法操作是很简单的,但是既有乘法又有加法涉及到先乘后加和先加后乘的顺序。
//

//

//
所以现在是如何将先加后成也可以转为lazy标记先乘后加也是正确的:
//

//
题解:

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+9;
vector<int>tree(4*N,0),arr(N,0),add(4*N,0),mul(4*N,1);
int n,q,Mod,op,x,y,k;

int lp(int p){return p<<1;}//2*p
int rp(int p){return p<<1 |1;}//2*p+1

void pushup(int p){
    tree[p]=tree[lp(p)]+tree[rp(p)];
    tree[p]%=Mod;
}

void tag_mul(int p,int c){
    add[p]*=c,add[p]%=Mod;//标记mul的当前节点有add标记,add标记需要*=c。就算没有add标记(=0),*=c,也等于0
    mul[p]*=c,mul[p]%=Mod;//mul标记
    tree[p]*=c,tree[p]%=Mod;
}

void pushdown(int p,int len){//下传标记(mul,add),先乘后加
   if(mul[p]!=1){//mul下传
       tag_mul(lp(p),mul[p]);
       tag_mul(rp(p),mul[p]);
        mul[p]=1;
   }
    if(add[p]!=0){//add下传
        add[lp(p)]+=add[p],add[lp(p)]%=Mod;
        add[rp(p)]+=add[p],add[rp(p)]%=Mod;
         tree[lp(p)]+=(len-(len>>1))*add[p],tree[lp(p)]%=Mod;//len是p节点的子节点的区间 。lp:(len-(len>>1)) , rp:(len>>1)
         tree[rp(p)]+=(len>>1)*add[p],tree[rp(p)]%=Mod;
          add[p]=0;
    }
}

void build(int s,int t,int p){
    if(s==t){
        tree[p]=arr[s],tree[p]%=Mod;
        return;
    }
     int m=(s+t)>>1;
     build(s,m,lp(p)),build(m+1,t,rp(p));
     pushup(p);
}

void update(int l,int r,int c,int s,int t,int p){
    if(l<=s && r>=t){
        if(op==1){tag_mul(p,c);}//乘法:mul标记
        else if(op==2){//加法:add标记
           add[p]+=c,add[p]%=Mod;
           tree[p]+=(t-s+1)*c,tree[p]%=Mod;
        }
        return;
    }
     pushdown(p,t-s+1);//len=t-s+1
    int m=(s+t)>>1;
     if(l<=m) {update(l,r,c,s,m,lp(p));}
     if(r>=m+1) {update(l,r,c,m+1,t,rp(p));}
     pushup(p);
}

int getsum(int l,int r,int s,int t,int p){
    if(l<=s && r>=t){
       return tree[p];
    }
    pushdown(p,t-s+1);
    int m=(s+t)>>1,sum=0;
    if(l<=m) {
        sum=getsum(l,r,s,m,lp(p));
        sum%=Mod;
    }
    if(r>=m+1) {
        sum+=getsum(l,r,m+1,t,rp(p));
        sum%=Mod;
    }
     return sum%Mod;
}

signed main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>n>>q>>Mod;
     for(int i=1;i<=n;i++) cin>>arr[i];
      build(1,n,1);

       while(q--){
           cin>>op;
           if(op==1 || op==2){//[x,y]*k, +k
              cin>>x>>y>>k;
               update(x,y,k,1,n,1);
           }
           if(op==3){
              cin>>x>>y;//查询[x,y]
               cout<<getsum(x,y,1,n,1)<<'\n';
           }
       }
    return 0;
}

标签:先乘,后加,tree,len,int,add,op,P3373,Mod
From: https://www.cnblogs.com/yongchaoD/p/18311957

相关文章

  • 整合Maven后加载不到Jar包解决方案
    简介:在整合Maven项目时,有时可能会遇到无法加载Jar包的问题。本文将提供解决此问题的方法和步骤,帮助您顺利解决加载不到Jar包的困境。当您在整合Maven项目后遇到无法加载Jar包的问题时,这通常是由于以下原因之一导致的:1、Maven依赖未正确配置:确保您的pom.xml文件中正确配置了......
  • P3373 【模板】线段树 2
    原题链接code#include<bits/stdc++.h>usingnamespacestd;#definelllonglonglla[100005]={0};lllazyadd[400005]={0};lllazymul[400005]={0};lltree[400005]={0};lln,q,m;voidbuild(llnode,llstart,llend){lazyadd[node]=0;lazymul[no......
  • (打标修改)读取每个文件夹内的txt,加入逗号后加入数据前
    importosdefrename_images_in_folder(folder_path,txt_prefix):"""在指定文件夹中重命名所有图片文件,将给定的txt_prefix添加到每个文件名的开头。"""forfilenameinos.listdir(folder_path):#检查文件是否为图片(简单地通过文件扩展名判断)......
  • 【线段树入门】P3373 线段树 2(区间乘加)
    //笔记-自用//#pragmaGCCoptimize("Ofast")//#pragmaGCCoptimize("unroll-loops")#define_CRT_SECURE_NO_WARNINGS#defineAll(a)a.begin(),a.end()#defineINF2147483647#include<bits/stdc++.h>#include<numeric>usingnamespac......
  • count++是先用后加还是先加后用
    在表达式count++中,++是后缀自增运算符,它的运算顺序是先使用变量的当前值,然后再将变量的值加1。换句话说,在执行count++表达式时,会先返回count的当前值,然后再将count的值加1。以下是一个示例代码,演示了count++表达式的运行过程:publicclassIncrementExample{public......
  • P3373 【模板】线段树 2
    【模板】线段树2如题,已知一个数列,你需要进行下面三种操作:将某区间每一个数乘上\(x\);将某区间每一个数加上\(x\);求出某区间每一个数的和。输入格式第一行包含三个整数\(n,q,m\),分别表示该数列数字的个数、操作的总个数和模数。第二行包含\(n\)个用空格分隔的整数,其中第\(i\)......
  • 视频汇聚平台EasyCVR从一分屏切换到四分屏后加载记录显示黑屏该如何解决?
    视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等,视频智能分析平台EasyCVR融合性强、开放度高、部署轻快,在智慧工地、智慧园区、智慧......
  • 视频汇聚平台EasyCVR从一分屏切换到四分屏后加载记录显示黑屏该如何解决?
    视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中,将分散的各类视频资源进行统一汇聚、整合、集中管理,实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等,视频智能分析平台EasyCVR融合性强、开放度高、部署轻快,在智慧工地、智慧园区、智慧......
  • 洛谷 P3373 总结
    洛谷P3373题意给定长度为\(n\)的整数序列,有以下三种操作共\(q\)次:将区间\([l,r]\)每一个数乘上\(k\);将区间\([l,r]\)每一个数加上\(k\);求出区间\([l,r]\)的区间和对\(m\)取模后的结果。\(1\leqslantn,q\leqslant10^5\)。思路这个题非常明确......
  • P3373 【模板】线段树 2
    【模板】线段树2如题,已知一个数列,你需要进行下面三种操作:将某区间每一个数乘上\(x\);将某区间每一个数加上\(x\);求出某区间每一个数的和。输入格式第一行包含三个整数\(n,q,m\),分别表示该数列数字的个数、操作的总个数和模数。第二行包含\(n\)个用空格分隔的整数,其......