题意:有点难懂; 初始序列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;
}
本文介绍了一种使用两棵线段树解决复杂区间操作问题的方法,通过倒序更新和懒惰传播技巧,有效地处理了区间加操作及递归性质的操作。详细解析了代码实现,包括初始化、更新、查询等核心步骤。
626

被折叠的 条评论
为什么被折叠?



