LG3374 【模板】樹狀數組 1
阿新 • • 發佈:2019-02-04
tchar temp ons ++i template std https freopen void
題意
如題,已知一個數列,你需要進行下面兩種操作:
- 將某一個數加上x
- 求出某區間每一個數的和
對於100%的數據:N<=500000,M<=500000
分析
cdq分治解決,參照mlystdcall的講解。
時間復雜度\(O((N+M) \log_2 (N+M))\)
代碼
#include<bits/stdc++.h> #define rg register #define il inline #define co const template<typename T>il T read() { rg T data=0,w=1; rg char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') w=-1; ch=getchar(); } while(isdigit(ch)) { data=data*10+ch-'0'; ch=getchar(); } return data*w; } template<typename T>il T read(rg T&x) { return x=read<T>(); } typedef long long ll; co int MAXN=5e5+1,MAXM=5e5+1,MAXQ=MAXN+MAXM*2; struct Query { int type,idx; ll val; bool operator<(co Query&x)co { return idx^x.idx?idx<x.idx:type<x.type; } }query[MAXQ],tmp[MAXQ]; ll ans[MAXQ]; int qidx=0,aidx=0; void cdq(int L,int R) // [L,R) { if(R-L<=1) return; int M=(L+R)/2; cdq(L,M),cdq(M,R); ll sum=0; int p=L,q=M,o=0; while(p<M&&q<R) { if(query[p]<query[q]) { if(query[p].type==1) sum+=query[p].val; tmp[o++]=query[p++]; } else { if(query[q].type==2) ans[query[q].val]-=sum; else if(query[q].type==3) ans[query[q].val]+=sum; tmp[o++]=query[q++]; } } while(p<M) tmp[o++]=query[p++]; while(q<R) { if(query[q].type==2) ans[query[q].val]-=sum; else if(query[q].type==3) ans[query[q].val]+=sum; tmp[o++]=query[q++]; } std::copy(tmp,tmp+o,query+L); } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); int n=read<int>(),m=read<int>(); for(int i=1;i<=n;++i) query[qidx].idx=i,query[qidx].type=1,query[qidx++].val=read<ll>(); for(int i=0;i<m;++i) { read(query[qidx].type); if(query[qidx].type==1) read(query[qidx].idx),read(query[qidx++].val); else { int l=read<int>(),r=read<int>(); query[qidx].idx=l-1,query[qidx++].val=aidx; query[qidx].type=3,query[qidx].idx=r,query[qidx++].val=aidx++; } } cdq(0,qidx); for(int i=0;i<aidx;++i) printf("%lld\n",ans[i]); return 0; }
LG3374 【模板】樹狀數組 1