CodeForces

来源:互联网 发布:遗传算法基本原理 编辑:程序博客网 时间:2024/06/16 22:39

传送门

题目大意:给一个长度为n的数组a, 和一个长度为m的数组b,和更新次数q; 函数f(j)的意思是   , 求出最小的函数值,然后会有q次更新数组a, 每次更新一个区间,从l到r之间每个值加x。输出每次更新之后所有f的最小值。

解题思路:我们可以通过技巧获得没更新之前的每个函数值,具体看代码。我们看公式可以看出一个规律,我们更新数组a时,如果更新的个数是偶数,等于没更新(数组a的系数正负1交替出现,每两项x就会抵消),如果是奇数,并且是从奇数开始的(l为奇数),那么就是f加上x, 如果l时偶数,那就减去x。(因为偶数的系数时-1,那么最后一个没抵消的那个数的系数也是-1)。每次更新都是将所有的f加上或者减去x,因此我们没必要每次都更新,我们只需保存下来就可以,保存到一个值中cur中的话,那么我们只需找到所有f中与cur相差最小的那个数即可.(函数是绝对值)。用二分查找即可。


AC代码:

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>using namespace std;int n, m, q;long long F[100000];long long B[100050];long long lower_find(long long x){int L =0, R = m-n;while(R > L){int mid = (R+L+1)/2;if(F[mid] ==  x) return 0;else if(F[mid] > x) R = mid-1;else L = mid;}long long x1, x2;x1 = abs(F[L]-x);if(L < m-n)x2 = abs(F[L+1]-x);else x2 =  9223372036854775807; return x1 < x2? x1 : x2;}int main(){scanf("%d%d%d", &n, &m, &q);long long f = 1, a, b;long long suma = 0,sumb = 0;for(int i=1; i<=n; i++){scanf("%lld", &a);suma += f*a;f = -f;}f = -1;for(int i=1; i<=m; i++){scanf("%lld", &B[i]);sumb += B[i] * f;f = -f;if(i>=n){int t = (i-n)%2 ? -1 : 1;F[i-n] = suma +  sumb * t;sumb += B[i-n+1] * t;}}sort(F, F+m-n+1);int l, r;long long x, cur = 0;printf("%lld\n", lower_find(0));for(int i=0; i<q; i++){scanf("%d%d%lld", &l, &r, &x);if((r-l)%2 == 0)if(l%2 == 1) cur += x;else cur -= x;printf("%lld\n", lower_find(-cur));}return 0;}


原创粉丝点击