线段树 非常简单的线段树
区间操作,比单点操作难那么一点点(一点点?)但是……似乎……并没有这么简单,这么多的子程序,检查比写都难,可我一直把想要求的区间左右端点和当前端点混着用,就一直不过,很尴尬
#include<cstdio> #include<iostream> using namespace std; int a[110000]; struct tree{ long long l,r,sum,addi,len; }st[100000]; void build(int z,int l,int r) { st[z].l=l,st[z].r=r,st[z].len=r-l+1; if(l==r) st[z].sum=a[l]; else { int mid=(l+r)/2; build(z*2,l,mid); build(z*2+1,mid+1,r); st[z].sum=st[z*2].sum+st[z*2+1].sum; } } void down(int x) { st[x*2].addi+=st[x].addi; st[x*2+1].addi+=st[x].addi; st[x*2].sum+=st[x].addi*st[x*2].len; st[x*2+1].sum+=st[x].addi*st[x*2+1].len; st[x].addi=0; } void add(int z,int l,int r,int adn) { if(st[z].l==l&&st[z].r==r) { st[z].addi+=adn; st[z].sum+=adn*st[z].len; return ; } if(st[z].addi) down(z); int mid=(st[z].l+st[z].r)/2; //这里mdzz,原来写的 int mid=(l+r)/2 if(r<=mid) add(z*2,l,r,adn); else if(l>mid) add(z*2+1,l,r,adn); else add(z*2,l,mid,adn),add(z*2+1,mid+1,r,adn); st[z].sum=st[z*2+1].sum+st[z*2].sum; } long long check(int z,int l,int r) { int left=st[z].l,right=st[z].r,mid=(left+right)/2; if(l==left&&r==right) return st[z].sum; else if(st[z].addi!=0) down(z); if(r<=mid) return check(z*2,l,r); else if(l>mid) return check(z*2+1,l,r); else return check(z*2,l,mid)+check(z*2+1,mid+1,r); } int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; build(1,1,n); for(int i=1;i<=m;i++) { int u,x,y,addn; cin>>u; if(u==1) { cin>>x>>y>>addn; add(1,x,y,addn); } if(u==2) { cin>>x>>y; cout<<check(1,x,y); } } return 0; }
线段树再见