差分プレフィックス合計
プレフィックスと操作
長さ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;
}
};