codevs 1082 线段树练习3
2017-08-14 15:06
281 查看
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int n,q; long long sum,a[200001]; struct tr { int l,r; long long v,ad; }s[2000001]; void build(int i,int l,int r) { s[i].l=l;s[i].r=r; if(l==r) { s[i].v=a[l];return; } build(i*2,l,(l+r)/2); build(i*2+1,(l+r)/2+1,r); s[i].v=s[i*2].v+s[i*2+1].v; } void ask(int i,int ll,int rr) { if(s[i].ad!=0) { s[i].v+=s[i].ad*(s[i].r-s[i].l+1); s[2*i].ad+=s[i].ad; s[2*i+1].ad+=s[i].ad; s[i].ad=0; } if(s[i].l>=ll&&s[i].r<=rr) { sum+=s[i].v; return; } int kk=i*2; if(s[kk].r>=ll)ask(kk,ll,rr); if(s[kk+1].l<=rr)ask(kk+1,ll,rr); } void add(int i,int ll,int rr,int x) { if(s[i].l>=ll&&s[i].r<=rr) { s[i].ad+=x; return; } if(ll>=s[i].l&&rr<=s[i].r)s[i].v+=x*(rr-ll+1); else s[i].v+=x*(min(abs(s[i].r-ll+1),abs(rr-s[i].l+1))); if(s[i].ad!=0) { s[i].v+=(s[i].r-s[i].l+1)*s[i].ad; s[2*i].ad+=s[i].ad; s[2*i+1].ad+=s[i].ad; s[i].ad=0; } int kk=i*2; if(s[kk].r>=ll)add(kk,ll,rr,x); if(s[kk+1].l<=rr)add(kk+1,ll,rr,x); } int main () { cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; cin>>q; build(1,1,n); for(int i=1;i<=q;i++) { int k;cin>>k; if(k==1) { int b,c,d; cin>>b>>c>>d; add(1,b,c,d); } if(k==2) { int b,c; cin>>b>>c; sum=0; ask(1,b,c); cout<<sum<<endl; } } }
相关文章推荐
- 【codevs】1082 线段树练习 3 <区间修改+区间和>
- codevs 1082 线段树练习 3(区间修改+区间求和)
- 【树状数组区间修改区间求和】codevs 1082 线段树练习 3
- 【codevs 1082】线段树练习三(区间修改+区间和)
- 【codevs 1082】线段树练习3
- AC日记——线段树练习三 codevs 1082 (分块尝试)
- 【codevs 1082】线段树练习 3
- 【Codevs】1082 线段树练习 3 && 线段树模板
- codevs1082 线段树练习3
- codevs1082线段树练习3(线段树)
- CODEVS-1082-线段树练习3-splay
- CODEVS 1080 线段树练习
- Wiki OI 1082 线段树练习 3 (区间更新,区间求和)
- 【codevs 1081】线段树练习 2
- codevs 4919 线段树练习4
- 1081 线段树练习 2 codevs
- 【codevs 1080~1082】线段树练习重做
- 【codevs1082】线段树练习3 线段树
- codevs 1080_线段树练习_树状数组
- 【CODE[VS]】1082 线段树练习 3 树状数组