P7479 四方喝彩
啊啊啊啊啊终于把这道题调出来了!!!
感觉都两三个月了,线段树真牛逼。
挂在这里纪念一下。
#include<bits/stdc++.h>
using namespace std;
#define N 2145140
#define M 1919810
#define ll long long
#define ls now<<1
#define rs now<<1|1
ll n,m,a[N],opt,l,r,x;
ll st[N],ed[N];
ll from[N],to[N];
ll mod=1e9+7;
struct tree{
ll l,r;
ll p,t;
ll sum1,sum2; //未封锁之数和与封锁之数和
ll f_locked; //封锁标记
ll len; //未被封锁数个数
}t[4*N];
void pushup(ll now){
if(!t[now].f_locked){
t[now].sum1=t[ls].sum1+t[rs].sum1;
t[now].sum2=t[ls].sum2+t[rs].sum2;
t[now].len=t[ls].len+t[rs].len;
t[now].sum1%=mod,t[now].sum2%=mod;
}
}
void pushdown(ll now){ //注意
t[ls].sum1=(t[ls].sum1*t[now].t+t[now].p*t[ls].len)%mod;
t[rs].sum1=(t[rs].sum1*t[now].t+t[now].p*t[rs].len)%mod;
if(!t[ls].f_locked) t[ls].t=(t[now].t*t[ls].t)%mod,t[ls].p=(t[ls].p*t[now].t+t[now].p)%mod;
if(!t[rs].f_locked) t[rs].t=(t[now].t*t[rs].t)%mod,t[rs].p=(t[rs].p*t[now].t+t[now].p)%mod;
t[now].p=0,t[now].t=1;
}
/*void pushdown(ll now){
if(t[now].t!=1){
ll tag=t[now].t;
t[ls].sum1=t[ls].sum1*tag%mod;
t[rs].sum1=t[rs].sum1*tag%mod;
if(!t[ls].f_locked) t[ls].p=t[ls].p*tag%mod,t[ls].t=t[ls].t*tag%mod;
if(!t[rs].f_locked) t[rs].p=t[rs].p*tag%mod,t[rs].t=t[rs].t*tag%mod;
}
if(t[now].p!=0){
ll tag=t[now].p;
t[ls].sum1=(t[ls].sum1+t[ls].len*tag)%mod;
t[rs].sum1=(t[rs].sum1+t[rs].len*tag)%mod;
if(t[ls].f_locked==0) t[ls].p=(t[ls].p+tag)%mod;
if(t[rs].f_locked==0) t[rs].p=(t[rs].p+tag)%mod;
}
t[now].p=0,t[now].t=1;
}*/
void build(ll now,ll l,ll r){
t[now].l=l,t[now].r=r,t[now].len=r-l+1;
t[now].p=0,t[now].t=1;
if(l==r){
t[now].sum1=a[l]%mod;
return;
}
ll mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(now);
}
void plus_(ll now,ll x,ll y,ll k){
if(t[now].f_locked) return;
if(t[now].l>=x&&t[now].r<=y){
t[now].sum1=(t[now].sum1+k*t[now].len)%mod;
t[now].p=(t[now].p+k)%mod;
return;
}
pushdown(now);
ll mid=(t[now].l+t[now].r)>>1;
if(x<=mid) plus_(ls,x,y,k);
if(y>mid) plus_(rs,x,y,k);
pushup(now);
}
void times(ll now,ll x,ll y,ll k){
if(t[now].f_locked) return;
if(t[now].l>=x&&t[now].r<=y){
t[now].sum1=(t[now].sum1*k)%mod;
t[now].p=(t[now].p*k)%mod;
t[now].t=(t[now].t*k)%mod;
return;
}
pushdown(now);
ll mid=(t[now].l+t[now].r)>>1;
if(x<=mid) times(ls,x,y,k);
if(y>mid) times(rs,x,y,k);
pushup(now);
}
//封锁操作
void locked(ll now,ll x,ll y,ll k){
if(t[now].l>=x&&t[now].r<=y){
if(l!=r) pushdown(now); //提前下传
if(!t[now].f_locked) t[now].sum2=(t[now].sum2+t[now].sum1)%mod,t[now].sum1=t[now].len=0;
++t[now].f_locked;
return;
}
pushdown(now);
ll mid=(t[now].l+t[now].r)>>1;
if(x<=mid) locked(ls,x,y,k);
if(y>mid) locked(rs,x,y,k);
pushup(now);
}
//解锁操作
void delete_locked(ll now,ll x,ll y){
if(t[now].l>=x&&t[now].r<=y){
--t[now].f_locked;
if(!t[now].f_locked){
if(t[now].l==t[now].r) swap(t[now].sum1,t[now].sum2),t[now].len=1;
//这个地方原来错了,写成了if(l==r)
else pushup(now); //上传解锁信息
}
return;
}
pushdown(now);
ll mid=(t[now].l+t[now].r)>>1;
if(x<=mid) delete_locked(ls,x,y);
if(y>mid) delete_locked(rs,x,y);
pushup(now);
}
ll query(ll now,ll x,ll y){
if(t[now].l>=x&&t[now].r<=y) return (t[now].sum1+t[now].sum2)%mod;
ll ans=0,mid=(t[now].l+t[now].r)>>1;
pushdown(now);
if(x<=mid) ans+=query(ls,x,y),ans%=mod;
if(y>mid) ans+=query(rs,x,y),ans%=mod;
ans%=mod;
return ans;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;++i) cin>>a[i];
build(1,1,n);
for(int i=1;i<=m;++i){
cin>>opt>>l>>r;
if(opt==1) cin>>x,plus_(1,l,r,x);
if(opt==2) cin>>x,times(1,l,r,x);
if(opt==3){
cin>>x;
locked(1,l,r,x);
st[i]=l,ed[i]=r;
to[i]=from[x+i],from[x+i]=i;
}
if(opt==4) cout<<query(1,l,r)<<'\n';
for(int j=from[i];j;j=to[j]) delete_locked(1,st[j],ed[j]);
}
return 0;
}
就是最后数组开到1e6,又加了读入优化才没有RE和TLE。
頑張って

早期作品
浙公网安备 33010602011771号