題目
n個數排成一列,有三種操作。1.給一段區間內的每個數乘上乙個非負整數。2.給一段區間內的每個數加上乙個非負整數.3.詢問一段區間的和模上p的值。
input
第一行兩個整數n(1≤n≤100000)表示數的個數,p(1≤p≤1000000000)表示模的值。接下來一行n個整數ai(0≤ai≤1000000000),接下來一行乙個整數m(1≤m≤100000)表示運算元量,接下來m行每行描述乙個操作。第一種操作描述:1 l r c(0≤c≤1000000000),表示把l到r這段區間每個數乘上乙個c。第二種操作描述:2 l r c(0≤c≤1000000000),表示把l到r這段區間每個數加上乙個c。第三種操作3 l r 表示詢問l到r這段區間內的數的和模上p的值。
output
對面每個詢問,輸出對應的答案,每個詢問佔一行。
sample input
7 43
1 2 3 4 5 6 7
5 1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7
sample output
2 35
8 hint
參考部落格:
題難的就是維護一段的加法,可以開另乙個標記,在更新標記時如果 * 前有加的話讓加的標記先乘也就是**中的
ss[root<<1].seg=(ss[root].segg*ss[root<<1].seg+ss[root].seg)%p;
就這句,神奇的是當先乘時由於加的標記為0就是,乘0 和普通的一樣
#include
#include
using namespace std;
long
long a[100009];
long
long p;
struct tree
ss[400009];
inline void pushup(int root)
inline void pushdown(int root,int l,int r)
void build(int l,int r,int root)
int m=(l+r)>>1;
build(l,m,root<<1);
build(m+1,r,root<<1|1);
pushup(root);
}void update(int root,int l,int r,int l,int r,long
long val,int op) // op 0 * 1 +
else
return;
}if(ss[root].seg!=0||ss[root].segg!=1)
int m=(l+r)>>1;
if(l<=m)
if(r>m)
pushup(root);
}long
long query(int root,int l,int r,int l,int r)
if(ss[root].seg!=0||ss[root].segg!=1)
int m=(l+r)>>1;
long
long
sum=0;
if(l<=m)
if(r>m)
return
sum;
}int main()
build(1,n,1);
cin>>m;
while(m--)
else
if(q==2)
else
注意要用long long wa了n發,慘~ ~ ~ ~ ~ poj2828 線段樹好題
題目意思是一群人排隊買票,然後後面乙個乙個的來人插隊,每個人都有乙個特殊的編號,每次告訴你他插在第幾個人的後面,問最後這串人的數字串最後是什麼。如果模擬來搞的話每次要乙個乙個的挪動人,最差的情況下每個人的位置都要變,是o n 2 的,200000的資料顯然是搞不動。正著思考麻煩的時候可以試著反向來思...
UESTC 1073 秋實大哥與線段樹
uestc 1073 學習本無底,前進莫徬徨。秋實大哥對一旁玩手機的學弟說道。秋實大哥是乙個愛學習的人,今天他剛剛學習了線段樹這個資料結構。為了檢驗自己的掌握程度,秋實大哥給自己出了乙個題,同時邀請大家一起來作。秋實大哥的題目要求你維護乙個序列,支援兩種操作 一種是修改某乙個元素的值 一種是詢問一段...
線段樹 模板題
problem description 已知乙個數列,你需要進行下面兩種操作 1.將某區間每乙個數加上x 2.求出某區間每乙個數的和 input 第一行包含兩個整數n m,分別表示該數列數字的個數和操作的總個數。第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。接下來m行每行包含...