https://ac.nowcoder.com/acm/contest/946/D
题意:
思路:注意后续的2操作,可能会调用前面的2操作,有点像递归操作
给每一个操作维护一个标记,从m到1遍历,每次利用自己的标记更新前面的操作的标记。
如果op==1,那么将此标记+1,如果op==2,将[l,r]的标记加上此标记数。
然后标记数就是每个操作的操作数。
最后执行op==1的操作,进行区间操作,每次区间[l,r]+标记数。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define FI first
#define SE second
const LL mod =1e9+7;
const int MX = 1e5+5;
LL a[MX],lazy[MX<<2],tree[MX<<2];
LL change[MX];int n,m;
int op[MX],xxx[MX],yyy[MX];
inline void pushUp(int root){
tree[root]=(tree[root<<1]+tree[root<<1|1])%mod;
}
void pushDown(int root,int le){
if(lazy[root]){
lazy[root<<1]+=lazy[root];lazy[root<<1]%=mod;
lazy[root<<1|1]+=lazy[root];lazy[root<<1|1]%=mod;
tree[root<<1]+=lazy[root]*(le-(le>>1));tree[root<<1]%=mod;
tree[root<<1|1]+=lazy[root]*(le>>1);tree[root<<1|1]%=mod;
lazy[root]=0;
}
}
void build(int l,int r,int root){
lazy[root]=0;
if(l==r){
tree[root]=a[l];
return;
}
int m=(l+r)>>1;
build(l,m,root<<1);
build(m+1,r,root<<1|1);
pushUp(root);
}
void update(int L,int R,LL c,int l,int r,int root){
if(l>=L&&r<=R){
lazy[root]+=c;lazy[root]%=mod;
tree[root]+=c*(r-l+1);tree[root]%=mod;
return;
}
pushDown(root,r-l+1);
int m=(l+r)>>1;
if(m>=L) update(L,R,c,l,m,root<<1);
if(m<R) update(L,R,c,m+1,r,root<<1|1);
pushUp(root);
}
LL query(int L,int R,int l,int r,int root){
if(l>=L&&r<=R)
return tree[root]%mod;
pushDown(root,r-l+1);
int m=(l+r)>>1;
LL re=0;
if(m>=L) re+=query(L,R,l,m,root<<1);
if(m<R) re+=query(L,R,m+1,r,root<<1|1);
return re%mod;;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&op[i],&xxx[i],&yyy[i]);
}
for(int i=m;i>=1;i--){
if(op[i]==1)update(i,i,1,1,m,1);
if(op[i]==2){
int getQ=query(i,i,1,m,1);
update(xxx[i],yyy[i],getQ+1,1,m,1);
}
}
for(int i=1;i<=m;i++){
change[i]=query(i,i,1,m,1);
}
memset(tree,0,sizeof(tree));
memset(lazy,0,sizeof(lazy));
memset(a,0,sizeof(a));
for(int i=1;i<=m;i++){
if(op[i]==1){
update(xxx[i],yyy[i],change[i],1,n,1);
}
}
for(int i=1;i<=n;i++){
printf("%lld ",query(i,i,1,n,1)%mod);
}
return 0;
}
/*
4 7
1 1 2
2 1 1
2 1 2
1 3 4
2 1 4
2 1 5
2 1 6
*/