5 条题解

  • 29
    @ 2023-6-24 16:23:44

    思路: 首先确定每个区间对应的增量,由题意可知,一个区间 [l, r] 中的所有数都会增加 1,而其他位置保持不变。因此我们可以将其拆成两个操作:

    • 将第 l 个位置加上 1
    • 将第 r+1 个位置减去 1

    接下来,我们可以遍历整个序列,求出前缀和,即每个位置 i 对应的值为原序列中前 i 个位置的增量之和。

    最后输出得到的新序列即可。

    需要注意的是,本题中序号从 1 开始,因此树状数组中的下标也需要从 1 开始。

    #include <iostream>
    
    using namespace std;
    
    const int N = 1e5 + 10;
    
    int n, m;
    int a[N], tr[N];
    
    int lowbit(int x) // 求 x 的二进制表示中最低位的 1 所对应的数值
    {
        return x & -x;
    }
    
    void add(int x, int c) // 将第 x 个位置加上 c
    {
        for (int i = x; i <= n; i += lowbit(i))
            tr[i] += c;
    }
    
    int sum(int x) // 求前 x 个数的和
    {
        int res = 0;
        for (int i = x; i; i -= lowbit(i))
            res += tr[i];
        return res;
    }
    
    int main()
    {
        cin >> n >> m;
        while (m--)
        {
            int l, r;
            cin >> l >> r;
            add(l, 1);
            add(r + 1, -1);
        }
    
        for (int i = 1; i <= n; i++)
            a[i] = sum(i);
    
        for (int i = 1; i <= n; i++)
            cout << a[i] << " ";
    
        return 0;
    }
    

    重要的事情说N遍!

    记得点赞! 记得点赞! 记得点赞!

  • 11
    @ 2023-6-30 10:13:04
    题目大意
             给定一个长度为n的序列,编号为1~n,序列中每个元素初始都为0,存在q次操作,每次操作能将编号在[l, r]之间的元素都加1,求q次操作后,序列中每个元素的数值。

    完整思路
            通过题意,可分析得知这是一道区间加法的裸题。

            使用差分的方法,建立差分数组b,并初始化为0。当区间[l, r]要加一时,令b[l] += 1且b[r + 1] -= 1即可。

            最终对差分数组b求前缀和,就能得到原序列q次操作后的结果。

    题解
    
    // 区间加法
    for (int i = 1; i <= q; i++)
    {
        int l, r;
        cin >> l >> r;
        b[l]++;
        b[r + 1]--;
    }
    
    
    • 3
      @ 2024-6-14 18:52:15

      运用差分知识点,将b[l]++后,a[i]一直到a[n]都加了1,所以为了使仅区间内加1,要将a[r+1]到a[n]都减1,即b[r+1]-- 代码:

      #include<iostream>
      using namespace std;
      int a[100005],b[100005];
      int main()
      {
          int n,q,l,r;
          cin>>n>>q;
          for(int i=1;i<=q;i++)
          {
              cin>>l>>r;
              b[l]+=1;
              b[r+1]-=1;
          }
          for(int i=1;i<=n;i++)
          {
              a[i]=a[i-1]+b[i];
              cout<<a[i]<<" ";
          }
          return 0;
      }
      

      **简洁的AC代码(确信)**🚀️

      • 1
        @ 2024-2-23 22:18:28
        #include <iostream>
        using namespace std;
        int a[100005], b[100005];
        int main()
        {
        	long long n, q;
        	cin >> n >> q;
            for (int i = 1; i <= q; i++)
            {
                int l, r;
                cin >> l >> r;
                b[l]+=1;
                b[r+1]-=1;
            }
        	for (int i = 1; i <= n; i++)
        	{
        		a[i]=a[i-1]+b[i];
        		cout << a[i] << " ";
        	}
        	return 0;
        }
        
        • -1
          @ 2024-6-15 20:28:56

          1<=n<=10^5,1<=q<=10^5 数据范围太大,差分也够呛,没有余额去 把a和b全初始化,所以全局,省一点

          • 1

          信息

          ID
          225
          时间
          1000ms
          内存
          256MiB
          难度
          4
          标签
          (无)
          递交数
          1361
          已通过
          660
          上传者