差分プレフィックス合計

差分プレフィックス合計

プレフィックスと操作

長さnの一連の数a1、a2、a3 ... anを与え、次にm個のクエリを与えると、各クエリは2つの数LとRを与え、区間[L、R]の数を要求します。接頭辞の合計を理解したことがない人がこの質問を見た場合、m個の質問について、それが与える間隔をトラバースし、毎回答えを計算するという考えかもしれません。この方法は確かに正しいですが、2つのサイクルを使用します、時間の複雑さはO(n * n)に達します。データの量がわずかに多い場合はタイムアウトになる可能性があり、プレフィックス合計法を使用してそれを行うと、時間を複雑にすることができます。次数はOに減少します。 (n + m)、これは計算時間を大幅に節約します。

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

次に、間隔内の数値の合計が必要です。tr[R] -tr [L-1]を使用できます。

差分

長さnの数a1、a2、a3 ... anのシーケンスを与え、a [L] 〜a [R]でm回の演算を要求します。

操作1:a [L] 〜a [R]のすべての要素にPを追加します

操作2:a [L] 〜a [R]のすべての要素からPを引きます

最後に、a [L] -a [R]?の要素の合計を見つけるための質問が与えられます。

あなたならどうしますか?m回の操作で毎回a [L] 〜a [R]をトラバースし、区間内の数値にPを加算または減算して、最後に接頭辞の合計を再度見つけると思うかもしれません。そうです、これは確かに正しい答えを得ることができますが、時間計算量はO(M * n + q)と同じくらい高いです。データ範囲1 <= n、m <= 1e5の場合、それは直接微妙なので、この方法実行可能ではありません。このとき、差が便利です。別の差配列br []を使用して、[a、b]の要素にcを同時に追加するなど、操作の各ステップを格納できます。その後、brを使用できます。 [a] + = c、br [b + 1]-= c、この場合、接頭辞の合計が再び見つかった場合は、区間内のすべての数値にcを追加できます。

#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;
}

木に水をまくニウニウ

タイトル説明

Niuniuは現在、庭にn本の木を1番目からn番目の順に並べています。ニウニウは毎日、気分に合わせて特定のセクションの木に水をやります。たとえば、ある日の散水間隔が[2,4]の場合、ニウニウはその日に2番目、3番目、4番目の木に水をやります。水をやると木が生えてきますので、簡単にするために、最初はすべての木の高さを0cmと仮定します。木は自然に毎日1cm成長し、水をやるたびに、その日はさらに1cm成長します。Niuniuは、m日単位で毎日間隔[l、r]を選択して、この間隔で木に水をやります。Niuniuは、m日後に高さが奇数である木がいくつあるかを知りたいのです。

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;
    }
};

おすすめ

転載: blog.csdn.net/weixin_51216553/article/details/111663775