筱玛爱线段树

筱玛爱线段树

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;
}
全部评论

相关推荐

牛客279957775号:铁暗恋
点赞 评论 收藏
分享
3 收藏 评论
分享
牛客网
牛客企业服务