Chapter 3. 數據結構 線段樹
阿新 • • 發佈:2017-05-17
int 區間修改 lld ref else 如果 ios 正在 step
Chapter 3. 數據結構 線段樹
Sylvia‘s I.單點修改,區間查詢.
模板:
//單點修改 區間求和
//1操作 單點修改
//2操作 區間求和 #include<cstdio> #include<iostream> using namespace std; #define MAXN 500005 int sum[MAXN<<2]; int n,m; void PushUp(int rt){//求和 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l,int r,intrt){//建樹 if (l==r){ scanf("%d",&sum[rt]); return; } int m=l+r>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); PushUp(rt); } void Update(int P,int Add,int l,int r,int rt){//單點修改 if (l==r){ sum[rt]+=Add; return; }int m=l+r>>1; if (P<=m) Update(P,Add,l,m,rt<<1); else Update(P,Add,m+1,r,rt<<1|1); PushUp(rt); } int Query(int L,int R,int l,int r,int rt){//區間查詢 if (L<=l&&r<=R) { return sum[rt]; } int m=l+r>>1; int ret=0;if (L<=m) ret+=Query(L,R,l,m,rt<<1); if (m<R) ret+=Query(L,R,m+1,r,rt<<1|1); return ret; } int step,x,k; int main (){ scanf("%d%d",&n,&m); build(1,n,1); for(int i=1;i<=m;i++){ scanf("%d%d%d",&step,&x,&k); if (step==1) Update(x,k,1,n,1); if (step==2) printf("%d\n",Query(x,k,1,n,1)); } return 0; }
Sylvia‘s II. 區間修改,區間查詢.
模板:參考自:bogo的線段樹模板
//1操作 乘法操作 //2操作 加法操作 //3操作 詢問區間和 //最後的結果對P取模 #include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> using namespace std; #define MAX 100003 #define LL long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct Segment_Tree{ LL sum[MAX<<2];//數組開四倍 LL lazy1[MAX<<2],lazy2[MAX<<2];//分別為乘法標記和加法標記 LL P;//取模 void PushUp(LL rt){//更新,對左右兒子求和 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; sum[rt]%=P;//別忘記取模 } void build(LL l,LL r,LL rt){//建樹 lazy1[rt]=1;//乘法標記記為1 lazy2[rt]=0;//加法標記記為0 if (l==r){ scanf("%lld",&sum[rt]); return; } LL m=l+r>>1; build(lson);//左子樹 build(rson);//右子樹 PushUp(rt);//及時更新 } void multiply (LL rt,LL x){//單乘 lazy2[rt]*=x;//(A[i]+lazy2[i])*lazy1[i]=A[i]*lazy1[i]+lazy2[i]*lazy1[i],所以加法標記要乘x lazy2[rt]%=P; lazy1[rt]*=x;//乘法標記當然也要乘…… lazy1[rt]%=P; sum[rt]*=x;//求和數組更要乘…… sum[rt]%=P; } void Add (LL rt,LL x,LL len){//單加 ,len為區間長度 lazy2[rt]=(lazy2[rt]+x)%P;//加法標記加 sum[rt]=(sum[rt]+(x*len)%P)%P;//求和數組加 } void PushDown (LL l,LL r,LL rt){ if (lazy1[rt]!=1){//如果有乘法標記 multiply(rt<<1,lazy1[rt]);//把標記下放到左兒子 multiply(rt<<1|1,lazy1[rt]);//把標記下放到右兒子 lazy1[rt]=1;//別忘記清除標記…… } if (lazy2[rt]){//如果有加法標記…… Add(rt<<1,lazy2[rt],(r+l>>1)-l+1); Add(rt<<1|1,lazy2[rt],r-(r+l>>1)); lazy2[rt]=0; } } void Addall(LL L,LL R,LL x,LL l,LL r,LL rt){//區間加 if (L<=l&&r<=R){//當前區間包含在需要查詢的區間中 Add(rt,x,r-l+1); return; } LL m=l+r>>1; PushDown(l,r,rt); if (L<=m) Addall(L,R,x,lson);//如果需查詢區間與左兒子有交集 if (m<R) Addall(L,R,x,rson);//如果需查詢區間與右兒子有交集 PushUp(rt);//及時更新 } void Mullall(LL L,LL R,LL x,LL l,LL r,LL rt){// 區間乘 ,與上面類似…… if (L<=l&&r<=R){ multiply(rt,x); return; } LL m=l+r>>1; PushDown(l,r,rt);//不要忘記查詢左右兒子之前先把標記下放,血的教訓…… if (L<=m) Mullall(L,R,x,lson); if (m<R) Mullall(L,R,x,rson); PushUp(rt); } LL Query(LL L,LL R,LL l,LL r,LL rt){//區間查詢 if (L<=l&&r<=R){ return sum[rt]; } LL ret=0; LL m=l+r>>1; PushDown(l,r,rt);// 不要忘記下放標記 if (L<=m) ret=(ret+Query(L,R,lson))%P; if (m<R) ret=(ret+Query(L,R,rson))%P; return ret; } }Seg; int main (){ LL n,m,step,x,y,z; scanf("%lld%lld%lld",&n,&m,&Seg.P); Seg.build(1,n,1);// for (int i=1;i<=m;i++){ scanf("%d",&step); switch(step){ case 1: scanf("%lld%lld%lld",&x,&y,&z); Seg.Mullall(x,y,z,1,n,1); break; case 2: scanf("%lld%lld%lld",&x,&y,&z); Seg.Addall(x,y,z,1,n,1); break; case 3: scanf("%lld%lld",&x,&y); printf("%lld\n",Seg.Query(x,y,1,n,1)); break; } } return 0; }
活著
余華
老人和牛漸漸遠去,我聽到老人粗啞的令人感動的嗓音從遠處傳來,
他的歌聲在空曠的傍晚像風一樣飄揚,
老人唱道:
少年去遊蕩,中年想掘藏,老年做和尚。
炊煙在農舍的屋頂裊裊升起,在霞光四射的空中分散後消隱了。
女人吆喝孩子的聲音此起彼伏,一個男人挑著糞桶從我跟前走過,扁擔吱呀吱呀一路響了過去。
慢慢地,田野趨向了寧靜,四周出現了模糊,霞光逐漸退去。
我知道黃昏正在轉瞬即逝,黑夜從天而降了。
我看到廣闊的土地袒露著結實的胸膛,
那是召喚的姿態,
就像,
女人召喚著她們的兒女,土地召喚著黑夜來臨。
Sylvia
二零一七年五月十七日
Chapter 3. 數據結構 線段樹