筱玛爱线段树
题意:1 l r [l,r]区间里的数加1。 2 l r [l,r]第l个操作到第r个操作重复执行一次。
思路:线段树加差分,区间修改,单值查询。
线段树版本:
#include<bits/stdc++.h>
using namespace std;
int tr[400005];
int op[100005],l[100005],r[100005];
int sum[100005];
const int mod=1e9+7;
int x;
void qu(int o,int l,int r,int ql){
x=(x+tr[o])%mod;
if(l==r)
return;
int m=(l+r)>>1;
if(ql<=m)
qu(o*2,l,m,ql);
else qu(o*2+1,m+1,r,ql);
}
void up(int o,int l,int r,int ql,int qr){
if(ql<=l&&qr>=r){
tr[o]=(tr[o]+x)%mod;
return;
}
int m=(l+r)>>1;
if(qr<=m)
up(o*2,l,m,ql,qr);
else if(ql>m)
up(o*2+1,m+1,r,ql,qr);
else{
up(o*2,l,m,ql,qr);
up(o*2+1,m+1,r,ql,qr);
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&op[i],&l[i],&r[i]);
}
tr[1]=1;
for(int i=m;i>=1;i--){
x=0;
qu(1,1,m,i);
if(op[i]==2){
up(1,1,m,l[i],r[i]);
}
else{
sum[l[i]]=(sum[l[i]]+x)%mod;
sum[r[i]+1]=(sum[r[i]+1]-x+mod)%mod;
}
}
for(int i=1;i<=n;i++){
sum[i]=(sum[i]+sum[i-1])%mod;
printf("%d ",sum[i]);
}
}
差分版本
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int l[100005],r[100005],op[100005];
ll d[100005],b[100005];
int main(){
int n,m;
scanf("%d%d",&n,&m);
memset(d,0,sizeof(d));
memset(b,0,sizeof(b));
for(int i=1;i<=m;i++){
scanf("%d%d%d",&op[i],&l[i],&r[i]);
}
d[m+1]=1;
d[0]--;
for(int i=m;i>=1;i--){
d[i]=(d[i+1]+d[i])%mod;
if(op[i]==2){
d[l[i]-1]=(d[l[i]-1]-d[i]+mod)%mod;
d[r[i]]=(d[r[i]]+d[i])%mod;
}
else{
b[l[i]]=(b[l[i]]+d[i])%mod;
b[r[i]+1]=(b[r[i]+1]-d[i]+mod)%mod;
}
}
for(int i=1;i<=n;i++){
b[i]=(b[i-1]+b[i])%mod;
printf("%lld ",b[i]);
}
}