前缀和与差分
P4552 差分
差分数组
差分数组()是一个可以表现数组内变量变化的一个数组,具体表现形式为:
-
\(b_1=a_1\)
-
\(b_i=a_i-a_{i-1}\)
对于这个数组有一些非常优雅的性质:
-
实现区间加显然可以左端点加 \(1\) ,右端点减 \(1\) 。
-
如果整个数组中的数全部为 \(x\) ,则 \(a_1=x\) 且 \(a_2=a_3=\) ... \(a_{i-1}=a_i=0\);
了解这一知识点后便可以非常轻松的完成这道题了。
Code.
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
//value
const int inf=2147483647;
const int mod=1e9+7;
int a[1000005],b[1000005];//function
void solve(){return;
}int main(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); // freopen(".in","r",stdin);
// freopen(".out","w",stdout);int n;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++)b[i]=a[i]-a[i-1];ll up=0,down=0;for(int i=2;i<=n;i++){if(b[i]<=0)down+=(-1*b[i]);else up+=b[i];}cout<<max(up,down)<<endl;cout<<abs(up-down)+1<<endl;return 0;
}
P9681 前缀和
通过观察题面,我们显然可以得到以下性质:
-
“幽默的数组”的形式显然是前面一串负数只有最后一个为正数
-
最后一位正数应大于前面负数和的绝对值
-
当数组只有一个正数时也是“幽默的数组”
-
对于一个长度大于 \(1\) 的“幽默的数组”,将左端点右移依然时“幽默的数组”
通过性质我们可以很容易得出一下做法:
将每一个正数的贡献均摊到前方的负数上,通过前缀和可以实现 \(O(1)\) 的查询。意到当负数在查询区间而正数不在时,负数的贡献就不应该被计算,故查询区间右端点应跳到最接近右端点的左端正数位置,此操作可以预处理出每一个数的左端正数,可 \(O(n)\) 处理。时间复杂度为线性,可以通过本题。