思路:这道题出发点就是为了练习线段树的板子题,但是我另外用了分块算法做了这道题,后面也会贴出相应的线段树解法。
分块算法:
#include<set> #include<queue> #include<vector> #include<string> #include<math.h> #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define maxn 200005 #define ll long long ll sum[maxn],mark[maxn]; int n,m,a[maxn],sq,size[maxn]; int st[maxn],ed[maxn],bel[maxn]; void init(int n){ sq=sqrt(n); for(int i=1;i<=sq;i++){ st[i]=n/sq*(i-1)+1; ed[i]=n/sq*i; } ed[sq]=n; for(int i=1;i<=sq;i++){ for(int j=st[i];j<=ed[i];j++) bel[j]=i; size[i]=ed[i]-st[i]+1; } } void update(int l,int r,int x){ if(bel[l]==bel[r]){ for(int i=l;i<=r;i++){ a[i]+=x; sum[bel[i]]+=x; } } else{ for(int i=l;i<=ed[bel[l]];i++){ a[i]+=x; sum[bel[i]]+=x; } for(int i=st[bel[r]];i<=r;i++){ a[i]+=x; sum[bel[i]]+=x; } for(int i=bel[l]+1;i<bel[r];i++) mark[i]+=x; } } ll query(int l,int r){ ll res=0; if(bel[l]==bel[r]){ for(int i=l;i<=r;i++) res+=a[i]+mark[bel[i]]; } else{ for(int i=l;i<=ed[bel[l]];i++) res+=a[i]+mark[bel[i]]; for(int i=st[bel[r]];i<=r;i++) res+=a[i]+mark[bel[i]]; for(int i=bel[l]+1;i<bel[r];i++) res+=sum[i]+mark[i]*size[i]; } return res; } int main(void){ int x,y,id,z; scanf("%d%d",&n,&m); init(n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=sq;i++) for(int j=st[i];j<=ed[i];j++) sum[i]+=a[j]; for(int i=1;i<=m;i++){ scanf("%d",&id); if(id==1){ scanf("%d%d%d",&x,&y,&z); update(x,y,z); } else{ scanf("%d%d",&x,&y); printf("%lld\n",query(x,y)); } } return 0; }线段树算法:
#include<queue> #include<vector> #include<string> #include<math.h> #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define maxn 600005 #define ll long long ll sum[maxn],lazy[maxn]; int n,m; void build(int id,int l,int r){ if(l==r){ scanf("%lld",&sum[id]); return; } int mid=(l+r)/2; build(id*2,l,mid); build(id*2+1,mid+1,r); sum[id]=sum[id*2]+sum[id*2+1]; } void pushDown(int id,int l,int r){ if(lazy[id]!=0){ int mid=(l+r)/2; sum[id*2]+=lazy[id]*(mid-l+1); sum[id*2+1]+=lazy[id]*(r-mid); lazy[id*2]+=lazy[id]; lazy[id*2+1]+=lazy[id]; lazy[id]=0; } } void update(int id,int l,int r,int ls,int rs,ll k){ if(l>r) return; if(ls<=l && rs>=r){ sum[id]+=k*(r-l+1); lazy[id]+=k; return; } pushDown(id,l,r); int mid=(l+r)/2; if(ls<=mid) update(id*2,l,mid,ls,rs,k); if(rs>mid) update(id*2+1,mid+1,r,ls,rs,k); sum[id]=sum[id*2]+sum[id*2+1]; } ll query(int id,int l,int r,int ls,int rs){ if(ls<=l && rs>=r) return sum[id]; ll res=0; int mid=(l+r)/2; pushDown(id,l,r); if(ls<=mid) res+=query(id*2,l,mid,ls,rs); if(rs>mid) res+=query(id*2+1,mid+1,r,ls,rs); return res; } int main(void){ int id,x,y; ll k; scanf("%d%d",&n,&m); build(1,1,n); for(int i=0;i<m;i++){ scanf("%d",&id); if(id==1){ scanf("%d%d%lld",&x,&y,&k); update(1,1,n,x,y,k); } else{ scanf("%d%d",&x,&y); printf("%lld\n",query(1,1,n,x,y)); } } return 0; }