Differential prefix sum

Differential prefix sum

Prefix and operation

If I give you a series of numbers a1, a2, a3...an of length n, and then give m queries, each query gives two numbers L and R, and asks for the number in the interval [L,R] What would you do? If someone who has not understood the prefix sum sees this question, the idea may be that for m questions, I traverse the interval it gives and calculate the answer every time. This method is of course Yes, but using two cycles, the time complexity reaches O(n*n). If the amount of data is slightly larger, it may time out, and if we use the prefix sum method to do it, we can make the time complicated The degree is reduced to O(n+m), which greatly saves computing time.

int tr[1005] = {0};
for(int i = 1; i <= n; i++)
    tr[i] += tr[i - 1];

Then you need the sum of the numbers in the interval, you can use tr[R]-tr[L-1]

Difference

Give you a sequence of numbers a1, a2, a3...an of length n, and require m operations on a[L]~a[R]:

Operation 1: Add P to all the elements in a[L]~a[R]

Operation 2: Subtract P from all the elements in a[L]~a[R]

Finally, a question is given to find the sum of the elements in a[L]-a[R]?

What would you do? You might think that I traverse a[L]~a[R] every time for m operations, add P or subtract P to the numbers in the interval, and finally find the prefix sum again. That's right, this can indeed get the correct answer, but the time complexity is as high as O(M*n+q). For the data range 1<=n, m<=1e5, it is directly tle, so This method is not feasible. At this time, the difference comes in handy. We can use another difference array br[] to store each step of the operation, such as adding c to the elements of [a,b] at the same time, then we can let br[a]+=c, br[b + 1]-=c, in this case, if you find the prefix sum again, you can add c to all the numbers in the interval

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int tr[10005] = {0};
    int br[10005] = {0};//差分数组
    int n, m, a, b, c;
    int add = 0;
    cin>>n>>m;//n是数组个数,m是进行的操作次数
    for(int i = 1; i <= n; i++)
    {
        cin>>tr[i];
    }
    for(int i = 1; i <= m; i++)
    {
        cin>>a>>b>>c;//对[a,b]的元素进行加c
        br[a]+=c;//差分数组
        br[b + 1]-=c;
    }
    for(int i = 1; i <= n; i++)
    {
        add+=br[i];//add是一直在相加的
        tr[i] += tr[i - 1] + add;//求前缀和,同时加上add,即加上该位置的元素经过操作后加的数
    }
    cin>>a>>b;//输入所需输出的区间
    cout<<tr[b] - tr[a - 1];

    //cout<<ans;
}

example

Niuniu watering the trees

Title description

Niuniu now has n trees in the garden, arranged in order from the first to the nth. Niuniu will water the trees in a certain section according to his mood every day. For example, if the watering interval is [2,4] on a certain day, Niuniu will water the second, third and fourth trees on that day. The trees will grow after being watered. In order to simplify the problem, we assume that the height of all trees is 0 cm at the beginning. The tree will naturally grow 1cm every day, and every time the tree is watered, it will grow an extra 1cm on the day. Niuniu chooses an interval [l,r] every day in m days to water the trees in this interval. Niuniu wants to know how many trees are odd in height after m days. Can you tell Niuniu?

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     * 返回m天后高度为奇数的树的数量
     * @param n int整型 
     * @param m int整型 
     * @param l int整型vector 
     * @param r int整型vector 
     * @return int整型
     */
    int oddnumber(int n, int m, vector<int>& l, vector<int>& r) {
        // write code here
        int  sum[200020] = {0};
        int ans = 0;
        for(int i = 0; i < m; i++)
        {
            sum[l[i]]++;
            sum[r[i] + 1]--;
        }
        for(int i = 1; i <= n; i++)
        {
            sum[i] += sum[i - 1];
        }
        for(int i = 1; i <= n; i++)
        {
            if((sum[i] + m) % 2 == 1)
                ans++;
        }
        return ans;
    }
};

Guess you like

Origin blog.csdn.net/weixin_51216553/article/details/111663775