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。

posted @ 2023-06-23 16:56  和蜀玩  阅读(34)  评论(0)    收藏  举报