筱玛爱线段树(两次差分)
筱玛爱线段树
https://ac.nowcoder.com/acm/problem/25737
题意:
有两个操作,操作一和操作二。
操作1: 区间[l:r] +1
操作2: 执行操作编号在[l,r]内的所有操作各一次
题解:
两次差分。
第一次差分,因为题目说保证r小于当前操作的编号,所以我们统计做了多少次操作1我们要倒着统计。
如果正着进行差分计算,行不通,,因为你不知道后面具体有哪些操作包含了当前操作.
第二次差分,运用第一次差分得出来的结果,也就是这个操作被操作了几次,操作了几次,那么这个区间就加几次。
代码:
/*Keep on going Never give up*/ //#pragma GCC optimize(3,"Ofast","inline") #include<bits/stdc++.h> #define int long long #define endl '\n' #define Accepted 0 #define AK main() #define I_can signed using namespace std; const int maxn =2e5+10; const int MaxN = 0x3f3f3f3f; const int MinN = 0xc0c0c00c; typedef long long ll; const int inf=0x3f3f3f3f; const ll mod=1e9+7; using namespace std; struct node{ int opt,l,r; }a[maxn]; int cnt[maxn],ans[maxn]; I_can AK{ ios::sync_with_stdio(false); int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ cin>>a[i].opt>>a[i].l>>a[i].r; } cnt[m]=1; for(int i=m;i>=1;i--){ cnt[i]=(cnt[i]+cnt[i+1])%mod; int l=a[i].l; int r=a[i].r; if(a[i].opt==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++){ int l=a[i].l; int r=a[i].r; if(a[i].opt==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; cout<<ans[i]%mod<<" "; } return 0; }
题解 文章被收录于专栏
主要写一些题目的题解