題目描述
如題,已知乙個數列,你需要進行下面兩種操作:
1.將某區間每乙個數加上x
2.求出某區間每乙個數的和
輸入格式
第一行包含兩個整數n、m,分別表示該數列數字的個數和操作的總個數。
第二行包含n個用空格分隔的整數,其中第i個數字表示數列第i項的初始值。
接下來m行每行包含3或4個整數,表示乙個操作,具體如下:
操作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複製118
20說明/提示
時空限制:1000ms,128m
資料規模:
對於30%的資料:n<=8,m<=10
對於70%的資料:n<=1000,m<=10000
對於100%的資料:n<=100000,m<=100000
(資料已經過加強_,保證在int64/long long資料範圍內)
樣例說明:
#include#includeusing namespace std;
long long read()
while(ch>='0'&&ch<='9')
return a*x;
}long long n,m,k,x,y,v;
long long a[100001],sum[400001],lazy[400001];
void build(long long node,long long l,long long r)
long long mid=(l+r)>>1;
build(node*2,l,mid);
build(node*2+1,mid+1,r);
sum[node]=sum[node*2]+sum[node*2+1];
}void pushdown(long long node,long long l,long long r)
long long mid=(l+r)>>1;
lazy[node*2]+=lazy[node];
lazy[node*2+1]+=lazy[node];
sum[node*2]+=lazy[node]*(mid-l+1);
sum[node*2+1]+=lazy[node]*(r-mid);
lazy[node]=0;
}void add(long long node,long long l,long long r,long long x,long long y,long long k)
pushdown(node,l,r);
long long mid=(l+r)>>1;
if(x<=mid)
if(y>mid)
sum[node]=sum[node*2]+sum[node*2+1];
}long long ask(long long node,long long l,long long r,long long x,long long y)
pushdown(node,l,r);
long long mid=(l+r)>>1;
long long rnt=0;
if(x<=mid)
if(y>mid)
return rnt;
}int main()
build(1,1,n);
for(int i=1;i<=m;i++)
else
}return 0;
}
模板 線段樹 1
區間修改 區間查詢 include define ll long long using namespace std ll a 100003 原數列 tree 400003 線段樹 delta 400003 標記 void update int now update多多益善 void build in...
線段樹模板(1)
本篇只對線段樹的基本應用介紹 即整區間單次改變,區間求和,單點改變和區間改變乙個道理,只把區間變成點。剩下的線段樹知識點類似 區間求逆序對,區間多次改變 同時 再 或者 或者 區間 合併,交 區間過大在改變時對p取模等放在後面學習給出。若只是需要求區間和或者單點改變,樹狀陣列是個好的選擇,但是其他的...
模板 線段樹1
洛谷p3374 線段樹的結構與樹狀陣列相似,但線段樹更加通用,維護的資料只要滿足區間加即可。線段樹是一棵二叉樹,每個節點表示乙個區間。假設某個節點表示 l,r mid l r 2,則它的左子節點表示 l,mid 右子節點表示 mid 1,r 若乙個節點的編號為x,則它的左子節點編號為x 2,右子節點...