传送门
解析:
码农题,直接按照覆盖,翻转,加法的优先级来维护标记,下传的时候也是按照这个优先级。
注意不要吝惜常数,该取模的地方一定要取模,不然调半天都不知道原因就真的尴尬了。(比如我)
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
#define int ll
inline ll getint(){
re ll num;
re char c;
re bool f=0;
while(!isdigit(c=gc()))if(c=='-')f=1;num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return f?-num:num;
}
inline void outint(ll a){
static char ch[23];
if(a==0)return (void)pc('0');
if(a<0)pc('-'),a=-a;
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
cs ll mod=1000000007;
cs int N=100005;
ll sum[N<<2],maxn[N<<2],minn[N<<2],add[N<<2],cover[N<<2],sqrsum[N<<2];
bool rev[N<<2],tag[N<<2];
inline void pushadd(cs int &k,cs int &l,cs int &r,cs ll &v){
sqrsum[k]=(sqrsum[k]+v*v%mod*(r-l+1)%mod+sum[k]%mod*2*v%mod+mod)%mod;
maxn[k]+=v;minn[k]+=v;add[k]+=v;
sum[k]+=v*(r-l+1);
}
inline void pushcover(cs int &k,cs int &l,cs int &r,cs ll &v){
tag[k]=true;
cover[k]=maxn[k]=minn[k]=v;
add[k]=0;rev[k]=false;
sum[k]=(r-l+1)*v;
sqrsum[k]=v*v%mod*(r-l+1)%mod;
}
inline void pushrev(cs int &k){
rev[k]^=1;
sum[k]=-sum[k];
add[k]=-add[k];
maxn[k]=-maxn[k];
minn[k]=-minn[k];
swap(maxn[k],minn[k]);
}
inline void pushdown(cs int &k,cs int &l,cs int &r){
int mid=(l+r)>>1;
if(tag[k]){
pushcover(k<<1,l,mid,cover[k]);
pushcover(k<<1|1,mid+1,r,cover[k]);
tag[k]=false;
}
if(rev[k]){
pushrev(k<<1);
pushrev(k<<1|1);
rev[k]=false;
}
if(add[k]){
pushadd(k<<1,l,mid,add[k]);
pushadd(k<<1|1,mid+1,r,add[k]);
add[k]=0;
}
}
inline void pushup(int k){
sum[k]=sum[k<<1]+sum[k<<1|1];
sqrsum[k]=(sqrsum[k<<1]+sqrsum[k<<1|1])%mod;
maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
minn[k]=min(minn[k<<1],minn[k<<1|1]);
}
inline void build(int k,int l,int r){
if(l==r){
maxn[k]=sum[k]=minn[k]=getint();
sqrsum[k]=sum[k]*sum[k]%mod;
return ;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
ll querysum(int k,int l,int r,cs int &ql,cs int &qr){
if(ql<=l&&r<=qr)return sum[k];
pushdown(k,l,r);
int mid=(l+r)>>1;
if(ql>mid)return querysum(k<<1|1,mid+1,r,ql,qr);
if(qr<=mid)return querysum(k<<1,l,mid,ql,qr);
return querysum(k<<1,l,mid,ql,qr)+querysum(k<<1|1,mid+1,r,ql,qr);
}
ll querymax(int k,int l,int r,cs int &ql,cs int &qr){
if(ql<=l&&r<=qr)return maxn[k];
pushdown(k,l,r);
int mid=(l+r)>>1;
if(ql>mid)return querymax(k<<1|1,mid+1,r,ql,qr);
if(qr<=mid)return querymax(k<<1,l,mid,ql,qr);
return max(querymax(k<<1,l,mid,ql,qr),querymax(k<<1|1,mid+1,r,ql,qr));
}
ll querymin(int k,int l,int r,cs int &ql,cs int &qr){
if(ql<=l&&r<=qr)return minn[k];
pushdown(k,l,r);
int mid=(l+r)>>1;
if(ql>mid)return querymin(k<<1|1,mid+1,r,ql,qr);
if(qr<=mid)return querymin(k<<1,l,mid,ql,qr);
return min(querymin(k<<1,l,mid,ql,qr),querymin(k<<1|1,mid+1,r,ql,qr));
}
ll querysqr(int k,int l,int r,cs int &ql,cs int &qr){
if(ql<=l&&r<=qr)return sqrsum[k];
pushdown(k,l,r);
int mid=(l+r)>>1;
if(ql>mid)return querysqr(k<<1|1,mid+1,r,ql,qr);
if(qr<=mid)return querysqr(k<<1,l,mid,ql,qr);
return (querysqr(k<<1,l,mid,ql,qr)+querysqr(k<<1|1,mid+1,r,ql,qr))%mod;
}
void modifyxor(int k,int l,int r,cs int &pos,cs ll &val){
if(l==r){
maxn[k]^=val;
minn[k]^=val;
sum[k]^=val;
sqrsum[k]=sum[k]%mod*sum[k]%mod;
return ;
}
pushdown(k,l,r);
int mid=(l+r)>>1;
if(pos<=mid)modifyxor(k<<1,l,mid,pos,val);
else modifyxor(k<<1|1,mid+1,r,pos,val);
pushup(k);
}
void modifyadd(int k,int l,int r,cs int &ql,cs int &qr,cs ll &val){
if(ql<=l&&r<=qr)return pushadd(k,l,r,val);
pushdown(k,l,r);
int mid=(l+r)>>1;
if(ql<=mid)modifyadd(k<<1,l,mid,ql,qr,val);
if(qr>mid)modifyadd(k<<1|1,mid+1,r,ql,qr,val);
pushup(k);
}
void modifyrev(int k,int l,int r,cs int &ql,cs int &qr){
if(ql<=l&&r<=qr)return pushrev(k);
pushdown(k,l,r);
int mid=(l+r)>>1;
if(ql<=mid)modifyrev(k<<1,l,mid,ql,qr);
if(qr>mid)modifyrev(k<<1|1,mid+1,r,ql,qr);
pushup(k);
}
void modifycover(int k,int l,int r,cs int &ql,cs int &qr,cs ll &val){
if(ql<=l&&r<=qr)return pushcover(k,l,r,val);
pushdown(k,l,r);
int mid=(l+r)>>1;
if(ql<=mid)modifycover(k<<1,l,mid,ql,qr,val);
if(qr>mid)modifycover(k<<1|1,mid+1,r,ql,qr,val);
pushup(k);
}
int n,m;
signed main(){
n=getint();
m=getint();
build(1,1,n);
while(m--){
ll op=getint(),l=getint(),r=getint();
ll x;
switch(op){
case 1:{outint((querysum(1,1,n,l,r)%mod+mod)%mod);pc('\n');break;}
case 2:{outint(querymax(1,1,n,l,r));pc('\n');break;}
case 3:{outint(querymin(1,1,n,l,r));pc('\n');break;}
case 4:{x=getint();modifyadd(1,1,n,l,r,x);break;}
case 5:{modifyxor(1,1,n,l,r);break;}
case 6:{printf("%.2f\n",querysum(1,1,n,l,r)*1.0/(r-l+1));break;}
case 7:{modifyrev(1,1,n,l,r);break;}
case 8:{x=getint();modifycover(1,1,n,l,r,x);break;}
case 9:{outint(querysqr(1,1,n,l,r));pc('\n');break;}
}
}
return 0;
}