1. 程式人生 > >某演算法的板子練習(三)

某演算法的板子練習(三)

碼量較大的資料結構……調起來也比較費勁……需要注意各個變數名不要寫錯

 

//線段樹板子 單點修改+區間修改+區間查詢(含lazy標記) 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define LL long long
#define MAXN 1000000
using namespace std;

inline int read()
{
    
int f=1,x=0; char ch=getchar(); while(ch<'0' || ch>'9') {if(ch=='-') f=-1; ch=getchar();} while(ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } int n,q; int a[MAXN+5]; LL seg_tree[MAXN*4+5],lazy_tag[MAXN*4+5]; void add(int l,int r,int k,int num)//lazy與區間和
{ lazy_tag[num]+=k; seg_tree[num]+=(r-l+1)*k; } void push_down(int l,int r,int mid,int num)//lazy標記下傳 { if(!lazy_tag[num]) return ; add(l,mid,lazy_tag[num],num*2); add(mid+1,r,lazy_tag[num],num*2+1); lazy_tag[num]=0; } void p_add(int k,int c,int l,int r,int num)//單點修改 { if
(l==r) { seg_tree[num]+=c; return ; } int mid=(l+r)/2; if(k<=mid) p_add(k,c,l,mid,num*2); else p_add(k,c,mid+1,r,num*2+1); seg_tree[num]=seg_tree[num*2]+seg_tree[num*2+1]; } void qadd(int ll,int rr,int k,int l,int r,int num)//區間修改 { if(ll<=l && rr>=r) { add(l,r,k,num); return ; } int mid=(l+r)/2; push_down(l,r,mid,num); if(ll<=mid) qadd(ll,rr,k,l,mid,num*2); if(rr>mid) qadd(ll,rr,k,mid+1,r,num*2+1); seg_tree[num]=seg_tree[num*2]+seg_tree[num*2+1]; } LL qfind(int ll,int rr,int l,int r,int num)//區間查詢 { if(ll<=l && r<=rr) { return seg_tree[num]; } int mid=(l+r)/2; LL ans=0; push_down(l,r,mid,num); if(ll<=mid) ans+=qfind(ll,rr,l,mid,num*2); if(rr>mid) ans+=qfind(ll,rr,mid+1,r,num*2+1); return ans; } int main() { int i; n=read(); q=read(); for(i=1;i<=n;i++) { a[i]=read(); p_add(i,a[i],1,n,1); } int f,a,b,k; for(i=1;i<=q;i++) { f=read(); a=read(); b=read(); if(f==1) { k=read(); qadd(a,b,k,1,n,1); } else printf("%lld\n",qfind(a,b,1,n,1)); } return 0; }

 

~NOIP2018 加油~