【原创】洛谷 LUOGU P3373 【模板】线段树2

P3373 【模板】线段树 2

题目描述

如题,已知一个数列,你需要进行下面两种操作:

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

(数据已经过加强^_^)

样例说明:

故输出应为17、2(40 mod 38=2)

乘法的优先级永远比加法高。

代码如下:

  1 // LUOGU 3373 【模板】线段树2
  2 // 2017.7.20 20:52
  3 #include<bits/stdc++.h>
  4 #define INF 0x3fffffff
  5 #define MAXN 100000
  6 #define MAXT MAXN*4
  7 using namespace std;
  8 typedef long long ll;
  9 int N,M,topt=0;
 10 ll P,a[MAXN+2];
 11 struct sgt_node{
 12     int lc,rc;
 13     ll sum,pls,mul;
 14     sgt_node(){pls=0,mul=INF;}
 15 }sgt[MAXT+2];
 16 int getint(){
 17     char ch=‘*‘;
 18     while(!isdigit(ch=getchar()));
 19     int num=ch-‘0‘;
 20     while(isdigit(ch=getchar()))num=num*10+ch-‘0‘;
 21     return num;
 22 }
 23 ll getll(){
 24     char ch=‘*‘;
 25     while(!isdigit(ch=getchar()));
 26     ll num=ch-‘0‘;
 27     while(isdigit(ch=getchar()))num=num*10+ch-‘0‘;
 28     return num;
 29 }
 30 #define lch sgt[now].lc
 31 #define rch sgt[now].rc
 32 #define smid ((l+r)>>1)
 33 void update(int now){
 34     sgt[now].sum=(sgt[lch].sum+sgt[rch].sum)%P;
 35 }
 36 void set_mul(int now,ll v){
 37     sgt[now].sum=(sgt[now].sum*v)%P;
 38     if(sgt[now].mul==INF)sgt[now].mul=v%P;
 39     else sgt[now].mul=(sgt[now].mul*v)%P;  // 必须为乘法!!!
 40     sgt[now].pls=(sgt[now].pls*v)%P;
 41 }
 42 void set_pls(int now,int l,int r,ll v){
 43     sgt[now].sum=(sgt[now].sum+v*(r-l+1))%P;
 44     sgt[now].pls=(sgt[now].pls+v)%P;
 45 }
 46 void push_down(int now,int l,int r){
 47     if(sgt[now].mul!=INF){
 48         set_mul(lch,sgt[now].mul);
 49         set_mul(rch,sgt[now].mul);
 50         sgt[now].mul=INF;
 51     }
 52     if(sgt[now].pls){
 53         set_pls(lch,l,smid,sgt[now].pls);
 54         set_pls(rch,smid+1,r,sgt[now].pls);
 55         sgt[now].pls=0;
 56     }
 57 }
 58 void Build_sgt(int &now,int l,int r){
 59     now=++topt;
 60     if(l==r){
 61         sgt[now].sum=a[l];
 62         return;
 63     }
 64     Build_sgt(lch,l,smid);
 65     Build_sgt(rch,smid+1,r);
 66     update(now);
 67 }
 68 ll Query_sgt(int now,int l,int r,int qx,int qy){
 69     if(l==qx&&r==qy)return sgt[now].sum;
 70     push_down(now,l,r);
 71     if(qy<=smid)return Query_sgt(lch,l,smid,qx,qy);
 72     if(qx>smid)return Query_sgt(rch,smid+1,r,qx,qy);
 73     return Query_sgt(lch,l,smid,qx,smid)+Query_sgt(rch,smid+1,r,smid+1,qy);
 74 }
 75 void Region_mul(int now,int l,int r,int x,int y,ll v){
 76     if(l==x&&r==y){
 77         set_mul(now,v);
 78         return;
 79     }
 80     push_down(now,l,r);
 81     if(y<=smid)Region_mul(lch,l,smid,x,y,v);
 82     else if(x>smid)Region_mul(rch,smid+1,r,x,y,v);
 83     else{
 84         Region_mul(lch,l,smid,x,smid,v);
 85         Region_mul(rch,smid+1,r,smid+1,y,v);
 86     }
 87     update(now);
 88 }
 89 void Region_pls(int now,int l,int r,int x,int y,ll v){
 90     if(l==x&&r==y){
 91         set_pls(now,l,r,v);
 92         return;
 93     }
 94     push_down(now,l,r);
 95     if(y<=smid)Region_pls(lch,l,smid,x,y,v);
 96     else if(x>smid)Region_pls(rch,smid+1,r,x,y,v);
 97     else{
 98         Region_pls(lch,l,smid,x,smid,v);
 99         Region_pls(rch,smid+1,r,smid+1,y,v);
100     }
101     update(now);
102 }
103 int main(){
104     N=getint(),M=getint(),P=getll();
105     for(int i=1;i<=N;i++)
106         a[i]=getll();
107     int root=0;
108     Build_sgt(root,1,N);
109     int op,x,y;
110     ll k;
111     for(int i=1;i<=M;i++){
112         op=getint();
113         switch(op){
114             case 1:
115                 x=getint(),y=getint(),k=getll();
116                 Region_mul(1,1,N,x,y,k);
117                 break;
118             case 2:
119                 x=getint(),y=getint(),k=getll();
120                 Region_pls(1,1,N,x,y,k);
121                 break;
122             case 3:
123                 x=getint(),y=getint();
124                 printf("%lld\n",Query_sgt(1,1,N,x,y)%P);
125                 break;
126         }
127     }
128     return 0;
129 }
时间: 2024-10-10 01:27:53

【原创】洛谷 LUOGU P3373 【模板】线段树2的相关文章

洛谷1558 色板游戏 线段树

我先立个Flag 我,这几天,要过1W道线段树题. 题目背景 阿宝上学了,今天老师拿来了一块很长的涂色板. 题目描述 色板长度为L,L是一个正整数,所以我们可以均匀地将它划分成L块1厘米长的小方格.并从左到右标记为1, 2, ... L.现在色板上只有一个颜色,老师告诉阿宝在色板上只能做两件事:1. "C A B C" 指在A到 B 号方格中涂上颜色 C.2. "P A B" 指老师的提问:A到 B号方格中有几种颜色.学校的颜料盒中一共有 T 种颜料.为简便起见,我

洛谷P3374 【模板】树状数组 1

P3374 [模板]树状数组 1 140通过 232提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 题目描述有误 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:

洛谷P3384 【模板】树链剖分

题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数N.M.R.P,分别表示树的结点个数.操作个数

洛谷P3368 【模板】树状数组 2

P3368 [模板]树状数组 2 102通过 206提交 题目提供者HansBug 标签 难度普及/提高- 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式

洛谷 P3374 【模板】树状数组 1 如题(单点修改+区间查询)

P3374 [模板]树状数组 1 时空限制1s / 128MB 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x k 含义:将第x个数加上k 操作2: 格式:2 x y 含义:输出区间[x,y]内

洛谷 P3368 【模板】树状数组 2 如题(区间修改+单点查询)

P3368 [模板]树状数组 2 时空限制1s / 128MB 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含2或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x 含义:输出

洛谷 [P3834] 可持久化线段树(主席树)

主席树可以存储线段树的历史状态,空间消耗很大,一般开45n即可 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <queue> #define lson l, mid #define rson mid+1, r #define ll long long using name

洛谷 P3374 【模板】树状数组 1 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:https://www.luogu.org/problem/show?pid=3374 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操

洛谷 P3368 【模板】树状数组 2

题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. 第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值. 接下来M行每行包含3或4个整数,表示一个操作,具体如下: 操作1: 格式:1 x y k 含义:将区间[x,y]内每个数加上k 操作2: 格式:2 x 含义:输出第x个数的值 输出格式: 输出包含若干行整数,即为所有操作2的结