筱玛爱线段树
筱玛爱线段树
https://ac.nowcoder.com/acm/problem/25737
题意:
一个长度为n的数组,初始值都是0,给出2个操作:
操作1: 区间[l:r] 加1
操作2: 执行操作编号在[l,r]内的所有操作各一次
求最后序列是多少?
分析:
1、首先操作2是在之前操作再进行一次,所以我们可以先统计当前这个位置被操作了多少次,怎么统计呢,每个2的操作是对前面操作的重复,
所以我们把操作从后往前跑,维护差分数组,求后缀和。
2、其次我们计算答案的时候,也是维护差分数组。最后答案就是前缀和跑一下。
详细看代码:
#include <bits/stdc++.h> #define int long long using namespace std; const int mod=1e9+7; const int N=1e5+100; int n,m; int op; struct Node { int op,l,r; }q[N]; int cnt[N]; int ans[N]; signed main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=m;i++) { scanf("%lld%lld%lld",&q[i].op,&q[i].l,&q[i].r); } cnt[m+1]=1; for(int i=m;i>=1;i--) { cnt[i]=(cnt[i]+cnt[i+1])%mod; int l=q[i].l; int r=q[i].r; if(q[i].op==2) { cnt[r]=(cnt[r]+cnt[i])%mod; cnt[l-1]=(cnt[l-1]-cnt[i]+mod)%mod; } } // for(int i=1;i<=m;i++) // { // printf("%d%c",cnt[i]," \n"[i==m]); // } for(int i=1;i<=m;i++) { int l=q[i].l; int r=q[i].r; if(q[i].op==1) { ans[l]=(ans[l]+cnt[i])%mod; ans[r+1]=(ans[r+1]-cnt[i]+mod)%mod; } } for(int i=1;i<=n;i++) { ans[i]=(ans[i]+ans[i-1])%mod; printf("%lld%c",ans[i]%mod," \n"[i==n]); } return 0; }