題目描述
如題,已知乙個數列,你需要進行下面三種操作:
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複製172
說明/提示
時空限制:1000ms,128m
資料規模:
對於30%的資料:n<=8,m<=10
對於70%的資料:n<=1000,m<=10000
對於100%的資料:n<=100000,m<=100000
(資料已經過加強_)
樣例說明:
故輸出應為17、2(40 mod 38=2)`#include
#include
using namespace std;
int p;
long long a[100007];
struct nodest[400007];
void bt(int root,int l,int r)
else
st[root].v%=p;
return;
}void pushdown(int root,int l,int r)
void ud1(int root, int stdl, int stdr, int l, int r, long long k)
pushdown(root, stdl, stdr);
int m=(stdl+stdr)/2;
ud1(root2, stdl, m, l, r, k);
ud1(root2+1, m+1, stdr, l, r, k);
st[root].v=(st[root2].v+st[root2+1].v)%p;
return;
}void ud2(int root, int stdl, int stdr, int l, int r, long long k)
pushdown(root, stdl, stdr);
int m=(stdl+stdr)/2;
ud2(root2, stdl, m, l, r, k);
ud2(root2+1, m+1, stdr, l, r, k);
st[root].v=(st[root2].v+st[root2+1].v)%p;
return;
}long long query(int root,int stdl,int stdr,int l,int r)
int main()
bt(1, 1, n);
while(m–)
else if(chk2)
else
}return 0;
}`
模板 線段樹2
模板 線段樹2 如題,已知乙個數列,你需要進行下面三種操作 1.將某區間每乙個數乘上x 2.將某區間每乙個數加上x 3.求出某區間每乙個數的和 第一行包含三個整數n m p,分別表示該數列數字的個數 操作的總個數和模數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行...
模板 線段樹 2
如題,已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.將某區間每乙個數乘上x 3.求出某區間每乙個數的和 輸入格式 第一行包含三個整數n m p,分別表示該數列數字的個數 操作的總個數和模數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包...
模板 維護序列2(線段樹)
取模取掛可真是令人質壁分離。兩兩乘積和可以直接用兩個區間的區間和相乘再加上兩個區間各自的乘積和得到,而相鄰乘積和直接兩段相加再加上左區間右端點與右區間左端點乘積就好了。注意 mod mod includeusing namespace std typedef long long ll const l...