UESTC 1597(線段樹好題)

2021-08-07 20:34:27 字數 1818 閱讀 6885

題目

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行每行包含...