题目描述 Description
给你N个数,有两种操作:
1:给区间[a,b]的所有数增加X
2:询问区间[a,b]的数的和。
输入描述 Input Description
第一行一个正整数n,接下来n行n个整数,
再接下来一个正整数Q,每行表示操作的个数,
如果第一个数是1,后接3个正整数,
表示在区间[a,b]内每个数增加X,如果是2,
表示操作2询问区间[a,b]的和是多少。
pascal选手请不要使用readln读入
输出描述 Output Description
对于每个询问输出一行一个答案
样例输入 Sample Input
3
1
2
3
2
1 2 3 2
2 2 3
样例输出 Sample Output
9
数据范围及提示 Data Size & Hint
数据范围
1<=n<=200000
1<=q<=200000
分类标签 Tags 点此展开
代码
堆
#include<cstdio> #include<iostream> using namespace std; #define N 801000 #define mid ((l+r)>>1) #define lc (k<<1) #define rc (k<<1|1) #define ll long long ll a[N],tag[N]; ll read(){ register ll f=1,x=0; register char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } void ins(int k,int l,int r,int i,int val){ if(l==r){a[k]=val;return;} if(i<=mid) ins(lc,l,mid,i,val); else ins(rc,mid+1,r,i,val); a[k]=a[lc]+a[rc]; } void pushdown(int k,int l,int r){ if(!tag[k]) return ; a[lc]+=tag[k]*(mid-l+1); a[rc]+=tag[k]*(r-mid); tag[lc]+=tag[k];tag[rc]+=tag[k];tag[k]=0; } void add(int k,int l,int r,int x,int y,int val){ if(l==x&&r==y){ tag[k]+=val;a[k]+=(r-l+1)*val;return ; } pushdown(k,l,r); if(y<=mid) add(lc,l,mid,x,y,val); else if(x>mid) add(rc,mid+1,r,x,y,val); else add(lc,l,mid,x,mid,val),add(rc,mid+1,r,mid+1,y,val); a[k]=a[lc]+a[rc]; } ll query(int k,int l,int r,int x,int y){ if(l==x&&r==y) return a[k]; pushdown(k,l,r); if(y<=mid) return query(lc,l,mid,x,y); else if(x>mid) return query(rc,mid+1,r,x,y); else return (query(lc,l,mid,x,mid)+query(rc,mid+1,r,mid+1,y)); } int main(){ ll n=read(),b; for(ll i=1;i<=n;i++) b=read(),ins(1,1,n,i,b); ll m=read(); for(ll i=1;i<=m;i++){ ll opt=read(); if(opt==1){ ll l=read(),r=read(),val=read(); if(l>r) swap(l,r); add(1,1,n,l,r,val); } else{ ll l=read(),r=read(); if(l>r) swap(l,r); printf("%lld ",query(1,1,n,l,r)); } } return 0; }
结构体
(便于维护和修改)
#include<cstdio> struct node{ int l,r,lch,rch,tage; long long sum; }tr[401000]; int a[201000]; int cnt; void build(int k,int l,int r){//不一样的建树 cnt++; tr[cnt].l=l;tr[cnt].r=r; if(l==r){ tr[cnt].sum=a[l];return ; } tr[k].lch=cnt+1; int mid=(l+r)>>1; build(cnt+1,l,mid); tr[k].rch=cnt+1; build(cnt+1,mid+1,r); tr[k].sum=tr[tr[k].lch].sum+tr[tr[k].rch].sum; } void pushdown(int k){ if(!tr[k].tage) return ;//下放--维护区 tr[tr[k].lch].sum+=tr[k].tage*(tr[tr[k].lch].r-tr[tr[k].lch].l+1); tr[tr[k].rch].sum+=tr[k].tage*(tr[tr[k].rch].r-tr[tr[k].rch].l+1); tr[tr[k].lch].tage+=tr[k].tage; tr[tr[k].rch].tage+=tr[k].tage; tr[k].tage=0; } void add(int k,int x,int y,int v){//在[l,r](初始是[1,n])中找到[x,y]修改 int l=tr[k].l,r=tr[k].r; if(l<=x&&r>=y){//数据上传(类似updata),更新父节点 tr[k].sum+=(y-x+1)*v; } if(l==x&&r==y){ tr[k].tage+=v;return ; } pushdown(k);//数据下传,更新子节点 int mid=(l+r)>>1; if(y<=mid) add(tr[k].lch,x,y,v); else if(x>mid) add(tr[k].rch,x,y,v); else add(tr[k].lch,x,mid,v),add(tr[k].rch,mid+1,y,v); } long long query(int k,int x,int y){//数据范围是long long int l=tr[k].l,r=tr[k].r; if(l==x&&r==y) return tr[k].sum; pushdown(k);//数据下传,更新子节点 int mid=(l+r)>>1; if(y<=mid) return query(tr[k].lch,x,y); else if(x>mid) return query(tr[k].rch,x,y); else return query(tr[k].lch,x,mid)+query(tr[k].rch,mid+1,y); } int main(){int n,m,l,r,v,opt; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a+i); build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d",&opt); if(opt==1){ scanf("%d%d%d",&l,&r,&v); add(1,l,r,v); } if(opt==2){ scanf("%d%d",&l,&r); long long ans=query(1,l,r); printf("%lld ",ans); } } return 0; }
最新版
#include<cstdio> #include<iostream> #define ll long long #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif #define lc k<<1 #define rc k<<1|1 using namespace std; inline ll read(){ register ll x=0;bool f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return f?x:-x; } const int N=2e5+10; const int M=N<<2; ll n,m,t1[N],a[M],tag[M]; void build(ll k,ll l,ll r){ if(l==r){ a[k]=t1[l];return ; } ll mid=l+r>>1; build(lc,l,mid); build(rc,mid+1,r); a[k]=a[lc]+a[rc]; } void pushdown(ll k,ll l,ll r){ if(!tag[k]) return ; tag[lc]+=tag[k]; tag[rc]+=tag[k]; ll mid=l+r>>1; a[lc]+=tag[k]*(mid-l+1); a[rc]+=tag[k]*(r-mid); tag[k]=0; } void ins(ll k,ll l,ll r,ll x,ll y,ll val){ if(l==x&&r==y){ a[k]+=(y-x+1)*val; tag[k]+=val; return ; } pushdown(k,l,r); ll mid=l+r>>1; if(y<=mid) ins(lc,l,mid,x,y,val); else if(x>mid) ins(rc,mid+1,r,x,y,val); else ins(lc,l,mid,x,mid,val),ins(rc,mid+1,r,mid+1,y,val); a[k]=a[lc]+a[rc]; } ll query(ll k,ll l,ll r,ll x,ll y){ if(l==x&&r==y) return a[k]; pushdown(k,l,r); ll mid=l+r>>1; if(y<=mid) return query(lc,l,mid,x,y); else if(x>mid) return query(rc,mid+1,r,x,y); else return query(lc,l,mid,x,mid)+query(rc,mid+1,r,mid+1,y); } int main(){ n=read(); for(ll i=1;i<=n;i++) t1[i]=read(); build(1,1,n); m=read(); for(ll i=1,opt,x,y,z;i<=m;i++){ opt=read(); if(opt==1){ x=read();y=read();z=read(); ins(1,1,n,x,y,z); } else{ x=read();y=read(); printf(LL" ",query(1,1,n,x,y)); } } return 0; }
可动态插点版
#include<cstdio> using namespace std; typedef long long ll; int read(){ int x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x; } const int N=2e5+10; const int M=N*4; int n,a[N]; int root,sz,ls[M],rs[M],tag[M]; ll sum[M]; void updata(int k){ sum[k]=sum[ls[k]]+sum[rs[k]]; } void pushdown(int k,int l,int r){ if(!tag[k]||l==r) return ; int mid=l+r>>1; tag[ls[k]]+=tag[k]; tag[rs[k]]+=tag[k]; sum[ls[k]]+=tag[k]*(mid-l+1); sum[rs[k]]+=tag[k]*(r-mid); tag[k]=0; } void build(int &k,int l,int r){ if(!k) k=++sz; if(l==r){sum[k]=a[l];return ;} int mid=l+r>>1; build(ls[k],l,mid); build(rs[k],mid+1,r); updata(k); } void change(int k,int l,int r,int x,int y,int val){ if(l==x&&r==y){ tag[k]+=val;sum[k]+=(r-l+1)*val;return ; } pushdown(k,l,r); int mid=l+r>>1; if(y<=mid) change(ls[k],l,mid,x,y,val); else if(x>mid) change(rs[k],mid+1,r,x,y,val); else change(ls[k],l,mid,x,mid,val),change(rs[k],mid+1,r,mid+1,y,val); updata(k); } ll query(int k,int l,int r,int x,int y){ if(l==x&&r==y) return sum[k]; pushdown(k,l,r); int mid=l+r>>1; if(y<=mid) return query(ls[k],l,mid,x,y); else if(x>mid) return query(rs[k],mid+1,r,x,y); else return query(ls[k],l,mid,x,mid)+query(rs[k],mid+1,r,mid+1,y); } int main(){ n=read();root=sz=1;//WA*1 for(int i=1;i<=n;i++) a[i]=read(); build(root,1,n); for(int cas=read();cas--;){ int opt=read(); if(opt==1){ int l=read(),r=read(),val=read(); change(root,1,n,l,r,val); } else{ int l=read(),r=read(); printf("%lld ",query(root,1,n,l,r)); } } return 0; }
分块版
#include<cstdio> #include<cmath> #include<iostream> using namespace std; typedef long long ll; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int F=501; int n,m,q; ll ans,sum[F],tag[F],b[F][F]; int main(){ n=read(); int m=sqrt(n)+1; for(int i=0;i<n;i++) b[i/m][i%m]=read(); for(int i=0;i<m;i++){ for(int j=0;j<m;j++){ sum[i]+=b[i][j]; } } q=read(); for(int opt,x,y,z,b1,b2,p1,p2;q--;){ opt=read(); if(opt&1){ x=read()-1;y=read()-1;z=read(); b1=x/m;b2=y/m; p1=x%m;p2=y%m; if(b1==b2){ for(int i=p1;i<=p2;i++) b[b1][i]+=z; sum[b1]+=(p2-p1+1)*z; } else{ for(int i=p1;i<m;i++) b[b1][i]+=z; sum[b1]+=(m-p1)*z; for(int i=b1+1;i<b2;i++) tag[i]+=z; for(int i=0;i<=p2;i++) b[b2][i]+=z; sum[b2]+=(p2+1)*z; } } else{ x=read()-1;y=read()-1;ans=0; b1=x/m;b2=y/m; p1=x%m;p2=y%m; if(b1==b2){ for(int i=p1;i<=p2;i++) ans+=b[b1][i]; ans+=(p2-p1+1)*tag[b1]; } else{ for(int i=p1;i<m;i++) ans+=b[b1][i]; ans+=(m-p1)*tag[b1]; for(int i=b1+1;i<b2;i++) ans+=sum[i]+tag[i]*m; for(int i=0;i<=p2;i++) ans+=b[b2][i]; ans+=(p2+1)*tag[b2]; } printf("%lld ",ans); } } return 0; }