K11734 完美照片(前缀和差分训练例题)

题目描述

科丁博士为了更好宣传科丁星系,想拍一张科丁战士的宣传照片。但是科丁博士想拍一张“完美的”照片,“完美的”是指是照片中的女战士和男战士的数量相等。他让N(1≤N≤50000)个科丁战士占成一条直线,每个战士都有各自的坐标,坐标的范围是0到10^9,同时每个战士用0和1来表示性别,0表示是女战士,1表示是男战士。
请帮助科丁博士计算出一个区间,使这个区间能够达到“完美”,并使得区间尽可能大。区间的大小为区间内最右边的战士的坐标减去最左边的战士的坐标。
输入中,每种性别至少有一名战士,没有两个战士的坐标相同。

输入格式

第一行,一个整数N,表示战士的数量
接下来N行,每行两个整数,分别代表战士i的性别和此战士的坐标

输出格式

1行,一个整数,最大的区间的大小。

输入输出样例

输入样例:                                                                  输出样例:

7                   &nbs
前缀和差分算法算法领域中用于处理数组区间操作的重要方法,二者互逆。 ### 前缀和算法 前缀和是指对于给定的数列,其前缀和数列定义为从首项到当前项的所有元素之和。对于一维数组,前缀和数组标准求法为:`for (int i = 1; i <= n; i++) { prefix[i] = prefix[i - 1] + a[i]; }`;也可直接在原数组上求前缀和:`for (int i = 1; i <= n; i++) { a[i]+=a[i-1]; }` [^3]。 二维前缀和用于二维空间上的面积求和与修改,基于容斥原理,其定义为:`b[i][j]=a[i][j]+b[i][j-1]+b[i-1][j]-b[i-1][j-1]` [^3]。 前缀和算法的应用场景主要是快速计算数组区间和。通过预先计算前缀和数组,可在 $O(1)$ 时间复杂度内得到任意区间的和。例如在 Java 代码中,对于给定的查询区间 `[l, r]`,区间和为 `s[r] - s[l - 1]` [^5]。 ### 差分算法 差分前缀和的逆运算,差分数组的前缀和数组就是原数组。差分数组 `diff` 定义为:`diff[i]=a[i]-a[i-1]`(`i >= 1`),对于区间 `[L, R]` 上的修改操作,可通过 `diff[L]+=c` 和 `diff[R + 1]-=c` 实现,即只在区间的起始位置和结束位置的下一个位置进行修改,后续通过求前缀和得到修改后的原数组 [^2][^3]。 二维差分数组的定义为:`diff[i][j]=a[i][j]-a[i-1][j]-a[i][j]+a[i-1][j-1]`,二维区间修改时,`diff[x1][y1]+=c`,`diff[x1][y2 + 1]-=c`,`diff[x2 + 1][y1]-=c`,`diff[x2][y2]+=c` [^3]。 差分算法主要用于区间修改操作,能将区间修改的时间复杂度从 $O(n)$ 降低到 $O(1)$,但只支持先修改后输出,不支持边修改边输出 [^3]。 ### 代码示例 以下是一维前缀和差分算法C++ 代码实现: ```cpp #include <iostream> using namespace std; const int N = 100000; int a[N] = {}, b[N] = {}; // a数组为前缀和数组,b数组为差分数组 int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> a[i]; // 将所给数列填入前缀和数组a b[i] = a[i] - a[i - 1]; // 同时利用相邻两项做差计算出差分数组b } while (m--) { int l, r, c; cin >> l >> r >> c; b[l] += c; // 差分数组在第l项加了c导致从第l项开始后面的前缀和数组每项也都加了c b[r + 1] -= c; // 差分数组在第r+1项减c会让前缀和数组从第r+1项开始少了c,正好和前面加的c抵消,实现[l,r]闭区间上a数组都加了c } for (int i = 1; i <= n; i++) { b[i] += b[i - 1]; // 求前i项和,并保存在b数组的第i项,即将b数组重构成新的前缀和数组 cout << b[i] << " "; } return 0; } ``` ### 应用例题 如 CF1343 D. Constant Palindrome Sum 就可使用前缀和差分算法解决 [^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值