Skip to main content
  1. Posts/

前缀和问题总结

·2 mins
Table of Contents
Note: This article is available in Chinese only. 本文暂无英文版本。 View original

There are two types of problems solvable by partial sum.

1.Problems which you are asked to answer some queries about the sum of a part of elements (without modify queries).

Solution of all of this problems are the same. You just need to know how to solve one of them.

Example : You are asked some queries on an array _a_1, _a_2, …a, n. Each query give you numbers l and r and you should print a__l + a__l + 1 + … + a__r .

Solution : You need to build another array _s_1, _s_2, …, s__n which s__i = _a_1 + _a_2 + … + a__i and answer is s__r - s__l - 1 .

2.Problems which you are asked to perform some queries asking you to modify a part of elements (without printing queries.)

Solution of all of this problems are the same. You just need to know how to solve one of them.

Example : You need to perform some queries on an array _a_1, _a_2, …a, n. Each query give you numbers l, r and v and for each i such that l ≤ i ≤ r you should increase a__i by v, and then after performing all queries, you should print the whole array.

Solution : You should have another array _p_1, _p_2, …, p__n which, all of its members are initially 0, for each query, you should increase p__l by v and decrease p__r + 1 by v .

An then, for each i, starting from 1 you should increase p__i by p__i - 1. So, final array would be _a_1 + _p_1, _a_2 + _p_2, …, a__n + p__n .

先说最简单也是最常见的一种。
#

sum[i]=sum[i-1]+a[i] (初始sum[0]=0,所以a[i]的下标最好从1开始) 询问得到[l,r]的和,答案为sum[r]-sum[l-1];

还有一种遇到相对较少的用法。 每次对数组a的某区间[l,r]内的每个数增加x。最后要求输出经过所有变换后的数组a。做法是:声明另一个数组p,当对区间[l,r]增加x时, p[l]+=x,p[r-1]-=x; 所有的变换完成后,另p[i]+=p[i-1] ,那么最后的答案就是p[i]+a[i](i:1..n) (可以这样理解:p[l]+=x,表示从x开始被增加x这个变换影响,一直影响到r,也就是从r+1取消这种变换的效果,所以p[r+1]-=x,然后处理前缀和,把标记在开头的变幻累计到每个元素)
#

#

此外:前缀和不一定是“和”,加法可以推广到任何有“前缀和性质”的运算,比如乘积,异或(虽然那样就应该不叫前缀“和”了2333)
#

cf617E异或前缀和

这些都是区间上的前缀和,我们可以进一步推广到树上。区间的前缀和是从第一个节点开始累加,树上则是从根节点开始做dfs然后累加。
#

树上前缀和hdu5416

Related

hdu 5416 CRB and Tree ( 2015 多校 #10 )

·2 mins
http://acm.hdu.edu.cn/showproblem.php?pid=5416 # 题意:给出一棵树(n<=1E5),定义二元函数函数f(u,v) (u可以等于v)表示节点u到节点v经过的路径的权值的异或和。给出q组查询(q<=10),每组一个s,问有多少对无序点对(u,v)满足f(u,v)=s. 思路:类似codeforces #340 div 2 E XOR and Favorite Number 先dfs,处理出从根节点都任意节点的异或前缀和。然后对于每个询问o(n)扫一遍,统计sum[i]^s出现多少次。 总的时间复杂度为O(Tqn);

hdu 5327 Olympiad (2015 多校 #4 )

·1 min
http://acm.hdu.edu.cn/showproblem.php?pid=5327 题意:问给出的区间[a,b]中有多少个美丽数,美丽数的定义是所有数字都不相同,如123是,100不是,333也不是。 思路:预处理1..100000的美丽数,可以把每个数字拆开放在set里,比较set的size和位数来实现。 然后用前缀和。

cf 611 A||codeforces goodbye 2015 C. New Year and Domino

·1 min
http://codeforces.com/contest/611/problem/C 题意:给出一个n*m的地图,.表示可以空,#表示墙。一个东西需要占两个相邻的格子,问给定一个矩形,放一个东西的方案数。 思路:q很大。。应该是先预处理出来直接调用答案。。。计数问题累加性。。应该是前缀和之类。。需要做的就是怎么标记。。我的做法是竖着放和横着放的个数分开来存。从左往右从上往下,每次标记到后一个点。然后二维的前缀和。然后每次询问的时候,去掉最上边和最左边两条边界上对应的多加的点。

codeforces 18 C. Stripe

·1 min
http://codeforces.com/contest/18/problem/C 题意:将一个序列分成两个非空的部分,保证和相等,问有多少种方法。 思路:做过一个三部分的。。。两部分直接一个前缀和就好了把。。。有一个需要注意的是。。判断负数是否是奇数的时候需要加个绝对值。。。