【前言】
作为一个什么数据结构都不会只会CDQ分治和分块的蒟蒻,面对区间加&区间求和这么难的问题,怎么可能会写线段树呢
于是,用CDQ分治解决区间加&区间求和这篇习作应运而生
【Part.I】区间加&区间求和的数据结构做法
【一】线段树
裸题...
1141ms
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define lc x<<1 #define rc x<<1|1 #define mid ((l+r)>>1) #define lson lc, l, mid #define rson rc, mid+1, r typedef long long ll; const int N=1e5+5; inline ll read(){ char c=getchar();ll x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,Q,op,x,y; struct SegmentTree{ struct meow{ ll sum, tag; } t[N<<2]; inline void paint(int x,int l,int r,ll v){ t[x].tag+= v; t[x].sum+= (r-l+1)*v; } inline void pushDown(int x,int l,int r){ if(t[x].tag){ paint(lson, t[x].tag); paint(rson, t[x].tag); t[x].tag=0; } } void build(int x,int l,int r){ if(l==r) t[x].sum=read(); else{ build(lson); build(rson); t[x].sum=t[lc].sum+t[rc].sum; } } void Add(int x,int l,int r,int ql,int qr,ll v){ if(ql<=l && r<=qr) paint(x,l,r,v); else{ pushDown(x,l,r); if(ql<=mid) Add(lson, ql, qr, v); if(mid<qr) Add(rson, ql, qr, v); t[x].sum=t[lc].sum+t[rc].sum; } } ll Que(int x,int l,int r,int ql,int qr){ if(ql<=l && r<=qr) return t[x].sum; else{ pushDown(x,l,r); ll ans=0; if(ql<=mid) ans+=Que(lson, ql, qr); if(mid<qr) ans+=Que(rson, ql, qr); return ans; } } }S; int main(){ //freopen("in","r",stdin); n=read(); Q=read(); S.build(1,1,n); while(Q--){ op=read();x=read();y=read(); if(op==1) S.Add(1,1,n,x,y,read() ); else printf("%lld\n", S.Que(1,1,n,x,y) ); } }