牛客49 D.筱瑪愛線段樹 (線段樹區間修改+思維)

題意:有點難懂; 初始序列a[n],值都爲0,有兩個操作,

          1.區間【l,r】內數++,

          2.執行操作編號在[l,r]內的所有操作各一次,保證r小於當前操作的編號。m次操作結束後,你要告訴馬爺A數組變成什麼樣子了。   意思就是說【l,r】區間(區間內的數此時爲操作的編號)內的數即以前的操作編號的,按這些操作編號再操作一次。

題解:建兩顆線段樹,一顆維護處究竟每個操作1的區間加了多少次1.   把M次操作倒着更新維護,因爲操作2有點遞歸的思想,正着無法在短時間內知道每個區間加多少1,

          第二棵在維護所有區間執行操作1後的,查詢即可。

細節:就是第一課樹實際是單點修改+區間修改,但是騷操作了一下,只用寫一個區間修改。

//題外話:權值線段樹沒有區間修改

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e5 + 5;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
int op[maxn],l[maxn],r[maxn];
ll sum[maxn*4],lazy[maxn*4];
void push(int p){
	sum[p]=(sum[p<<1]+sum[p<<1|1])%mod;
}
void pushdown(int l,int r,int p){
	int mid=(l+r)/2;
	if(lazy[p]){
		lazy[p<<1]+=lazy[p]; lazy[p<<1]%=mod;
		lazy[p<<1|1]+=lazy[p]; lazy[p<<1|1]%=mod;
		sum[p<<1]+=lazy[p]*(mid-l+1); sum[p<<1]%=mod;
		sum[p<<1|1]+=lazy[p]*(r-mid); sum[p<<1|1]%=mod;
		lazy[p]=0;
	}
}
void build(int l,int r,int p){
	if(l==r){
		sum[p]=0; lazy[p]=0;
		return ;
	}
	int mid=(l+r)/2;
	build(l,mid,p<<1);
	build(mid+1,r,p<<1|1);
	push(p);
}
void update(int l,int r,int L,int R,ll val,int p){
	if(L<=l&&r<=R){
		lazy[p]+=val; lazy[p]%=mod;
		sum[p]+=val*(r-l+1); sum[p]%=mod;
		return ;
	}
	pushdown(l,r,p);
	int mid=(l+r)/2;
	if(L<=mid) update(l,mid,L,R,val,p<<1);
	if(R>mid)  update(mid+1,r,L,R,val,p<<1|1);
	push(p);
}
ll query(int l,int r,int L,int R,int p){
	if(L<=l&&r<=R){
		return sum[p]%mod;
	}
	pushdown(l,r,p);
	int mid=(l+r)/2;
	ll ans=0;
	if(L<=mid) ans+=query(l,mid,L,R,p<<1);
	if(R>mid) ans+=query(mid+1,r,L,R,p<<1|1); 
	return ans%mod;
}
ll tp[maxn];
int main(){
	int n,m; cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>op[i]>>l[i]>>r[i];
	}
	build(1,m,1);
	for(int i=m;i>=1;i--){
		if(op[i]==1) update(1,m,i,i,1,1);
		else{
			ll Q=query(1,m,i,i,1);//從後往前確定操作1的次數
			update(1,m,l[i],r[i],Q+1,1);
		}
	}
	for(int i=1;i<=m;i++){//每個操作1究竟執行幾次
		tp[i]=query(1,m,i,i,1);
	}
	memset(lazy,0,sizeof(lazy));
	memset(sum,0,sizeof(sum));
	build(1,n,1);
	for(int i=1;i<=m;i++){
		if(op[i]==1){
			update(1,n,l[i],r[i],tp[i],1);
		}
	}
	for(int i=1;i<=n;i++){
		cout<<query(1,n,i,i,1)<<" ";
	}
	cout<<endl;
	
} 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章