线段树模板(区间加、区间乘)


传送门

题目描述

如题,已知一个数列,你需要进行下面两种操作:
1.将某区间每一个数加上x
2.将某区间每一个数乘上x
3.求出某区间每一个数的和

输入输出格式

输入格式
第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。
接下来M行每行包含3或4个整数,表示一个操作,具体如下:
操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k
操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k
操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果
输出格式
输出包含若干行整数,即为所有操作3的结果。

输入输出样例

输入样例#1

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

输出样例#1

17
2

说明

时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=8,M<=10
对于70%的数据:N<=1000,M<=10000
对于100%的数据:N<=100000,M<=100000

思路

普通的线段树模板,只需要再加一个乘的标记就行,但要注意在pushdowm的时候应该先乘后加(你要不嫌麻烦写一块儿我也没意见),乘的时候加法标记也要跟着乘

C++代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rr register
using namespace std;

typedef long long LL;
const int maxn=1e5+10;
int n,m,Q;
int a[maxn];

inline LL read(){//珂朵莉版快读~~ 
    LL chtholly=0,willem=1;char c=getchar();
    while(c<'0' || c>'9'){if(c=='-')willem=-1;c=getchar();}
    while(c<='9' && c>='0'){chtholly=chtholly*10+(LL)(c-'0');c=getchar();}
    return chtholly*willem;
}

struct segment_tree{
#define lson (u<<1)
#define rson (u<<1|1)
    LL sum[maxn<<2],addv[maxn<<2],mul[maxn<<2],p;
    inline void pushup(int u){sum[u]=(sum[lson]+sum[rson])%p;}
    inline void build(int u,int l,int r){
        addv[u]=0,mul[u]=1;
        if(l==r){sum[u]=a[l];return;}
        int mid=(l+r)>>1;
        build(lson,l,mid);build(rson,mid+1,r);
        pushup(u);
    }
    inline void pushdown(int u,int lc,int rc){
        if(mul[u]!=1){
            addv[lson]=(addv[lson]*mul[u])%p;addv[rson]=(addv[rson]*mul[u])%p;
            mul[lson]=(mul[lson]*mul[u])%p;mul[rson]=(mul[rson]*mul[u])%p;
            sum[lson]=(sum[lson]*mul[u])%p;sum[rson]=(sum[rson]*mul[u])%p;
        }
        if(addv[u]!=0){
            addv[lson]=(addv[lson]+addv[u])%p;addv[rson]=(addv[rson]+addv[u])%p;
            sum[lson]=(sum[lson]+addv[u]*lc%p)%p;sum[rson]=(sum[rson]+addv[u]*rc%p)%p;
        }
        addv[u]=0,mul[u]=1;
    }
    inline void update_add(int u,int l,int r,int ql,int qr,int val){
        //区间加 
        if(ql<=l && r<=qr){
            sum[u]=(sum[u]+val*(r-l+1)%p)%p;
            addv[u]=(addv[u]+val)%p;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(u,mid-l+1,r-mid);
        if(ql<=mid) update_add(lson,l,mid,ql,qr,val);
        if(qr>mid) update_add(rson,mid+1,r,ql,qr,val);
        pushup(u);
    }
    inline void update_mul(int u,int l,int r,int ql,int qr,int val){
        //区间乘 
        if(ql<=l && r<=qr){
            mul[u]=mul[u]*val%p;
            sum[u]=sum[u]*val%p;
            addv[u]=addv[u]*val%p;
            return;
        }
        int mid=(l+r)>>1;
        pushdown(u,mid-l+1,r-mid);
        if(ql<=mid) update_mul(lson,l,mid,ql,qr,val);
        if(qr>mid) update_mul(rson,mid+1,r,ql,qr,val);
        pushup(u);
    }
    inline LL query(int u,int l,int r,int ql,int qr){
        if(ql<=l && r<=qr)return sum[u];
        int mid=(l+r)>>1;
        pushdown(u,mid-l+1,r-mid);
        LL ret=0LL;
        if(ql<=mid) ret=(ret+query(lson,l,mid,ql,qr))%p;
        if(qr>mid) ret=(ret+query(rson,mid+1,r,ql,qr))%p;
        return ret%p;
    }
}tr;

int main(){
    n=read(),m=read(),tr.p=read();
    for(rr int i=1;i<=n;++i)a[i]=read();
    tr.build(1,1,n);
    while(m--){
        Q=read();
        int l=read(),r=read();
        if(Q==2){
            int x=read();
            tr.update_add(1,1,n,l,r,x);
        }
        if(Q==1){
            int x=read();
            tr.update_mul(1,1,n,l,r,x);
        }
        if(Q==3){
            LL ans=tr.query(1,1,n,l,r);
            printf("%lld\n",ans);
        }
    }
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 树形动态规划,顾名思义就是树+DP,先分别回顾一下基本内容吧:动态规划:问题可以分解成若干相互联系的阶段,在每一个...
    Mr_chong阅读 1,396评论 0 2
  • 转圈游戏 题目 n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏。按照顺时针方向给 n 个位置编号,从0 到 ...
    bbqub阅读 351评论 0 0
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,663评论 0 33
  • 还是有悬而未决的事,还是有许多想了又想不知如何是好的事还是不能全力与爱的人恣意前行... 有时候会觉得“一地鸡毛”...
    mo清夜无尘阅读 73评论 0 1
  • 感觉自己像个动物一样,被观摩,被嘲笑,像脱光了衣服站在人前,无地自容!
    与二有缘的女孩阅读 326评论 0 0