如題,已知乙個數列,你需要進行下面兩種操作:
將某區間每乙個數加上 k。
求出某區間每乙個數的和。
第一行包含兩個整數 n, m,分別表示該數列數字的個數和操作的總個數。
第二行包含 n 個用空格分隔的整數,其中第 i個數字表示數列第 i項的初始值。
接下來 m行每行包含 33 或 44 個整數,表示乙個操作,具體如下:
1.1 x y k:將區間 [x, y]內每個數加上 k。
2.2 x y:輸出區間 [x, y]內每個數的和。
輸出包含若干行整數,即為所有操作 2 的結果。
輸入 #1
5 51 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
輸出 #1
11820
對於 30% 的資料:n≤8,m≤10。
對於 70% 的資料:n≤10^3,m≤10^4。
對於 100% 的資料:1≤n,m≤10^5。
保證任意時刻數列中任意元素的和在 [−2^63,2^63]內。
find線段樹新盲區!——線段樹的懶惰標記
1 #include2 #include3 #include4 #include5using
namespace
std;
6long
long tree[300001],lazy[300001];7
long
long sum,a[300001
],n,m;
8int build(int i,int left,int
right)
13int mid=(left+right)/2
;14 build(i*2
,left,mid);
15 build(i*2+1,mid+1
,right);
16 tree[i]=tree[i*2]+tree[i*2+1
];17}18
int f(int p,int l,int r,int
val)
22int push_down(int p,int l,int
r)28
int turn(int i,int left,int right,int b_l,int b_r,long
long
val)
34push_down(i,left,right);//更新左右節點(查詢時遇到一次更新一次)
35int mid=(left+right)/2;36
if(b_l<=mid) turn(i*2
,left,mid,b_l,b_r,val);
37if(mid+1
<=b_r) turn(i*2+1,mid+1
,right,b_l,b_r,val);
38 tree[i]=tree[i*2]+tree[i*2+1
];39}40
int search(int i,int left,int right,int b_l,int
b_r)
46push_down(i,left,right);//這也是
47int mid=(left+right)/2;48
if(b_l<=mid) search(i*2
,left,mid,b_l,b_r);
49if(mid+1
<=b_r) search(i*2+1,mid+1
,right,b_l,b_r);50}
51int
main()
66int
l,r;
67 scanf("
%d%d
",&l,&r);
68 sum=0
;69 search(1,1
,n,l,r);
70 printf("
%lld\n
",sum);71}
72 }
字首查詢(字典樹 線段樹懶惰標記)
描述 在乙個 minecraft 村莊中,村長有這一本小寫字母構成的名冊 字串的表 每個名字旁邊都記錄著這位村民的聲望值,而且有的村民還和別人同名。隨著時間的推移,因為沒有村民死亡,這個名冊變得十分大。現在需要您來幫忙維護這個名冊,支援下列 4 種操作 1.插入新人名 si,聲望為 ai 2.給定名...
2018 08 18 線段樹(線段樹)
線段樹 描述請你維護乙個線段樹 支援一下操作 a x l r 區間 and x o x l r區間 or x x x l r 區間 xor x s l r 區間求和 輸入乙個數 t表示資料組數 乙個數n表示初始序列長 m表示查詢 隨後n個整數 接下來m次詢問 如上 輸出所以s次詢問的答案 樣例輸入 ...
區間更新和懶惰標記的線段樹
普通版本的線段樹進行的是單點更新和區間查詢.對於帶有懶惰標記的線段樹,則可以進行區間更新.代表了這個結點的值已經被更新過了,但是沒有進行子樹的結點值更改操作,用lazy陣列標記一下.所以,每次進行值的更新和查詢操作,每到乙個有 lazy 標記的結點,必須進行向下更新.區間替換 include inc...