区间加&区间求和
#include<iostream> #include<cstdio> #include<cstdlib> #define maxn 400010 #define ll long long using namespace std; template<typename T> inline void read(T &x){ x=0; bool flag=0; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') flag=1; for(;isdigit(c);c=getchar()) x=x*10+(c^48); if(flag) x=-x; } ll n,m,s[maxn],num,x,y,k; ll t[maxn],tag[maxn]; void pushup(ll x){ t[x]=t[x<<1]+t[x<<1|1];//=t[2*x]+t[2*x+1] } void build(ll x,ll l,ll r){ if(l==r){ t[x]=s[l]; return ; } ll mid=(l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); pushup(x); } void tag_(ll x,ll len,ll k){ t[x]+=len*k; tag[x]+=k; } void pushdown(ll x,ll l,ll r){ if(tag[x]){ ll mid=(l+r)>>1; tag_(x<<1,mid-l+1,tag[x]); tag_(x<<1|1,r-mid,tag[x]); tag[x]=0; } } void change(ll x,ll l,ll r,ll cl,ll cr,ll k){ pushdown(x,l,r); if(cl<=l&&r<=cr) return tag_(x,r-l+1,k); ll mid=(l+r)>>1; if(cl<=mid) change(x<<1,l,mid,cl,cr,k); if(cr>=mid+1) change(x<<1|1,mid+1,r,cl,cr,k); pushup(x); } ll query(ll x,ll l,ll r,ll ql,ll qr){ pushdown(x,l,r); if(ql<=l&&r<=qr) return t[x]; ll mid=(l+r)>>1; ll ret=0; if(ql<=mid) ret+=query(x<<1,l,mid,ql,qr); if(qr>=mid+1) ret+=query(x<<1|1,mid+1,r,ql,qr); return ret; } int main(){ read(n),read(m); for(int i=1;i<=n;i++) read(s[i]); build(1,1,n); for(int i=1;i<=m;i++){ cin>>num; if(num==1) { cin>>x>>y>>k; change(1,1,n,x,y,k); } if(num==2) { cin>>x>>y; cout<<query(1,1,n,x,y)<<endl; } } return 0; }
70分 ↑
#include<iostream> #include<cstdio> #include<cstdlib> #define maxn 800010 #define ll long long using namespace std; template<typename T> inline void read(T &x){ x=0; bool flag=0; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') flag=1; for(;isdigit(c);c=getchar()) x=x*10+(c^48); if(flag) x=-x; } ll n,m,s[maxn],num,x,y,k; ll t[maxn],tag[maxn]; void pushup(ll x){ t[x]=t[x<<1]+t[x<<1|1];//=t[2*x]+t[2*x+1] } void build(ll x,ll l,ll r){ if(l==r){ t[x]=s[l]; return ; } ll mid=(l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); pushup(x); } void tag_(ll x,ll len,ll k){ t[x]+=len*k; tag[x]+=k; } void pushdown(ll x,ll l,ll r){ if(tag[x]){ ll mid=(l+r)>>1; tag_(x<<1,mid-l+1,tag[x]); tag_(x<<1|1,r-mid,tag[x]); tag[x]=0; } } void change(ll x,ll l,ll r,ll cl,ll cr,ll k){ pushdown(x,l,r); if(cl<=l&&r<=cr) {tag_(x,r-l+1,k); return ;} ll mid=(l+r)>>1; if(cl<=mid) change(x<<1,l,mid,cl,cr,k); if(cr>=mid+1) change(x<<1|1,mid+1,r,cl,cr,k); pushup(x); } ll query(ll x,ll l,ll r,ll ql,ll qr){ pushdown(x,l,r); if(ql<=l&&r<=qr) return t[x]; ll mid=(l+r)>>1; ll ret=0; if(ql<=mid) ret+=query(x<<1,l,mid,ql,qr); if(qr>=mid+1) ret+=query(x<<1|1,mid+1,r,ql,qr); return ret; } int main(){ read(n),read(m); for(int i=1;i<=n;i++) read(s[i]); build(1,1,n); for(int i=1;i<=m;i++){ cin>>num; if(num==1) { cin>>x>>y>>k; change(1,1,n,x,y,k); } if(num==2) { cin>>x>>y; cout<<query(1,1,n,x,y)<<endl; } } return 0; }
AC ↑
我也不知道为啥4倍空间过不了要开8倍才能过
#include<iostream> #include<cstdio> #include<cstdlib> #define maxn 400010 #define ll long long using namespace std; template<typename T> inline void read(T &x){ x=0; bool flag=0; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') flag=1; for(;isdigit(c);c=getchar()) x=x*10+(c^48); if(flag) x=-x; } ll n,m,s[maxn],num,x,y,k; ll t[maxn],tag[maxn]; void pushup(ll x){ t[x]=t[x<<1]+t[x<<1|1];//=t[2*x]+t[2*x+1] } void build(ll x,ll l,ll r){ if(l==r){ t[x]=s[l]; return ; } ll mid=(l+r)>>1; build(x<<1,l,mid); build(x<<1|1,mid+1,r); pushup(x); } void tag_(ll x,ll len,ll k){ t[x]+=len*k; tag[x]+=k; } void pushdown(ll x,ll l,ll r){ if(tag[x]){ ll mid=(l+r)>>1; tag_(x<<1,mid-l+1,tag[x]); tag_(x<<1|1,r-mid,tag[x]); tag[x]=0; } } void change(ll x,ll l,ll r,ll cl,ll cr,ll k){ if(cl<=l&&r<=cr) {tag_(x,r-l+1,k); return ;} pushdown(x,l,r); ll mid=(l+r)>>1; if(cl<=mid) change(x<<1,l,mid,cl,cr,k); if(cr>=mid+1) change(x<<1|1,mid+1,r,cl,cr,k); pushup(x); } ll query(ll x,ll l,ll r,ll ql,ll qr){ if(ql<=l&&r<=qr) return t[x]; pushdown(x,l,r); ll mid=(l+r)>>1; ll ret=0; if(ql<=mid) ret+=query(x<<1,l,mid,ql,qr); if(qr>=mid+1) ret+=query(x<<1|1,mid+1,r,ql,qr); return ret; } int main(){ read(n),read(m); for(int i=1;i<=n;i++) read(s[i]); build(1,1,n); for(int i=1;i<=m;i++){ cin>>num; if(num==1) { cin>>x>>y>>k; change(1,1,n,x,y,k); } if(num==2) { cin>>x>>y; cout<<query(1,1,n,x,y)<<endl; } } return 0; }
AC ↑
好了我知道了,千万注意pushdown要放在return后面,这样4倍空间就能过了~
区间乘&区间加&区间求和
#include<iostream> #include<cstdio> #include<cstdlib> #define maxn 400010 #define ll long long using namespace std; template<typename T> inline void read(T &x){ x=0; bool flag=0; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c=='-') flag=1; for(;isdigit(c);c=getchar()) x=x*10+(c^48); if(flag) x=-x; } ll n,m,p,s[maxn],num,x,y,k; ll t[maxn],tag1[maxn],tag2[maxn];//tag1->mul tag2->sum void pushup(ll x){ (t[x]=t[2*x]+t[2*x+1])%=p; } void build(ll x,ll l,ll r){ tag1[x]=1,tag2[x]=0; if(l==r){ t[x]=s[l]; return ; } ll mid=(l+r)/2; build(x*2,l,mid); build(x*2+1,mid+1,r); pushup(x); } void pushdown(ll x,ll l,ll r){ ll mid=(l+r)/2; t[x*2]=(t[x*2]*tag1[x]%p+(mid-l+1)*tag2[x])%p; t[x*2+1]=(t[x*2+1]*tag1[x]%p+(r-mid)*tag2[x])%p; tag1[x*2]=tag1[x*2]*tag1[x]%p; tag1[x*2+1]=tag1[x*2+1]*tag1[x]%p; tag2[x*2]=(tag2[x*2]*tag1[x]+tag2[x])%p; tag2[x*2+1]=(tag2[x*2+1]*tag1[x]+tag2[x])%p; tag1[x]=1,tag2[x]=0; } /* 一定要先乘后加( 没人愿意乘法逆元先加后乘吧...... (a+b)*c=a*c+b*c; a*c+b=a*c+b; */ void mul(ll x,ll l ,ll r,ll cl,ll cr,ll k){ if(cl<=l&&r<=cr){ (t[x]*=k)%=p; (tag1[x]*=k)%=p; (tag2[x]*=k)%=p; return ; } pushdown(x,l,r); ll mid=(l+r)/2; if(cl<=mid) mul(x*2,l,mid,cl,cr,k); if(cr>=mid+1) mul(x*2+1,mid+1,r,cl,cr,k); pushup(x); } void sum(ll x,ll l ,ll r,ll cl,ll cr,ll k){ if(cl<=l&&r<=cr){ (t[x]+=(r-l+1)*k%p)%=p; (tag2[x]+=k)%=p; return ; } pushdown(x,l,r); ll mid=(l+r)/2; if(cl<=mid) sum(x*2,l,mid,cl,cr,k); if(cr>=mid+1) sum(x*2+1,mid+1,r,cl,cr,k); pushup(x); } ll query(ll x,ll l,ll r,ll ql,ll qr){ if(ql<=l&&r<=qr) return t[x]; pushdown(x,l,r); ll mid=(l+r)/2,ret=0; if(ql<=mid) (ret+=query(x*2,l,mid,ql,qr))%=p; if(qr>=mid+1) (ret+=query(x*2+1,mid+1,r,ql,qr))%=p; return ret; } int main(){ read(n),read(m),read(p); for(int i=1;i<=n;i++) read(s[i]); build(1,1,n); for(int i=1;i<=m;i++){ read(num);read(x),read(y); if(num==1){ read(k); mul(1,1,n,x,y,k); } if(num==2){ read(k); sum(1,1,n,x,y,k); } if(num==3){ cout<<query(1,1,n,x,y)%p<<endl; } } return 0; }