筱玛爱线段树(两次差分)

筱玛爱线段树

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;

}
题解 文章被收录于专栏

主要写一些题目的题解

全部评论

相关推荐

11-14 16:13
已编辑
重庆科技大学 测试工程师
Amazarashi66:不进帖子我都知道🐮❤️网什么含金量
点赞 评论 收藏
分享
三年之期已到我的offer快到碗里来:9硕都比不上9本
点赞 评论 收藏
分享
3 1 评论
分享
牛客网
牛客企业服务