博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Sums of Sums
阅读量:6315 次
发布时间:2019-06-22

本文共 4605 字,大约阅读时间需要 15 分钟。

Alice presented her friend Bob with an array of N positive integers, indexed from 1 to N. She challenged Bob with many queries of the form "what is the sum of the numbers between these two indexes?" But Bob was able to solve the problem too easily.

Alice took her array and found all N*(N+1)/2 non-empty subarrays of it. She found the sum of each subarray, and then sorted those values (in nondecreasing order) to create a new array, indexed from 1 to N*(N+1)/2. For example, for an initial array [2, 3, 2], Alice would generate the subarrays [2], [3], [2], [2, 3], [3, 2], and [2, 3, 2] (note that [2, 2], for example, is NOT a subarray). Then she'd take the sums -- 2, 3, 2, 5, 5, 7 -- and sort them to get a new array of [2, 2, 3, 5, 5, 7].

Alice has given the initial array to Bob, along with Q queries of the form "what is the sum of the numbers from index Li to Ri, inclusive, in the new array?" Now Bob's in trouble! Can you help him out?

Input

The first line of the input gives the number of test cases, T. T test cases follow. Each test case begins with one line with two space-separated integers N and Q, denoting the number of elements in the initial array and the number of Alice's queries. Then, there is one line with N space-separated integers, denoting the elements of Alice's initial array. Finally, there are Q more lines with two space-separated integers each: Li and Ri, the inclusive index bounds for the i-th query.

Output

For each test case, output one line with Case #x:, where x is the test case number (starting from 1). Then output Q more lines, each with one integer, representing the answers to the queries (in the order they were asked).

Limits

1 ≤ T ≤ 10.

1 ≤ Q ≤ 20.
1 ≤ each element of the initial array ≤ 100.
1 ≤ LiRi ≤ N*(N+1)/2.

Small dataset

1 ≤ N ≤ 103.

Large dataset

1 ≤ N ≤ 200000.

Sample

Input
 
Output
 
15 55 4 3 2 11 11 101 153 84 11
Case #1:1451052648

In sample case #1, Alice's new array would be: [1, 2, 3, 3, 4, 5, 5, 6, 7, 9, 9, 10, 12, 14, 15].

这是今年APAC2017 practice round 的D题,最后一题.需要求子数组和排序序列的L到R的和.暴力方法是枚举所有子数组,求和,排序,枚举所有子数组的复杂度为O(N*(N+1)), 对这个数组进行排序的复杂度为O(N^2)log(N^2), 空间复杂度为O(N^2).这种解法在数组大小为10万量级以上会爆内存,速度也会很慢,所以需要优化.所以要进行的是在不枚举所有子数组的和的情况下,进行L和R的查找,一个比较好的方法是对值二分.

即对子数组和的范围进行二分,开始 l = 0, r = sum(array). 通过不断二分找到一个数n, 使小于其值的子数组的数目等于或者刚刚大于L或者R.

对于一个特定的数值n如何查找小于或者等于该值子数组的数目呢,在prefix sum 数组上使用双指针进行遍历是一个非常好的解法. 开始left = 0(prefix sum第一个是dummy值),right=1.开始进行判断.最终可能正好找到这个值n, 和小于等于这个值的子数组的数目刚好等于L或者R, 不理想的情况是找不到这个值,也就是L中的只包含了和等于某个值n*的部分子数组.此时就得对二分结束的l和r做判断,找到一个刚好大于L或者的R的第一个值.

另外计算子数组和的求和也可以通过 prefix sum 的prefix sum来进行.但是一定要注意prefix sum本身就有dummy,要先除去这个dummy再计算prefix sum.最终这个算法的时间复杂度为O(nlogn).

__author__ = 'xiaqing'def get_sum(psum, ss, k, N):    #bit devide by value    l = psum[0]    r = psum[-1]    while l+1 < r:        mid = (l+r)/2        count = 0        lp = 0        rp = 1        for lp in xrange(N):            while rp <= N and psum[rp] - psum[lp] <= mid :                rp += 1            count += rp - lp -1        if count < k:            l = mid        elif count > k:            r = mid        else:            break    if l + 1 < r:        l = mid #use l as the finally calculate element    else:        lp = 0        rp = 1        count = 0        for lp in xrange(N):            while rp <= N and psum[rp] - psum[lp] <= l :                rp += 1            count += rp - lp -1        if count < k: # make sure that l is the first value that make the count larger or equal to k, l is not qualified, count r's number            l = r            lp = 0            rp = 1            count = 0            for lp in xrange(N):                while rp <= N and psum[rp] - psum[lp] <= l :                    rp += 1                count += rp - lp -1# how to calculate the last output    lp = 0    rp = 1    ans = 0    for lp in xrange(N):        while rp <= N and psum[rp] - psum[lp] <= l :            rp += 1        ans += ss[rp-1] - ss[lp] - (rp-lp-1)*psum[lp]    ans -= (count - k)*l    return ansinput = open('./D-large-practice.in','r')output = open('./D-large-practice.out','w')T = int(input.readline().strip())for n in xrange(T):    output.writelines('Case #%s:\n'%(n+1))    N,Q = map(int, input.readline().strip().split())    array = map(int, input.readline().strip().split())    psum = [0]    ss = [0]    for i in array:        psum.append(psum[-1]+i)    for i in psum[1:]:  #除去dummy        ss.append(ss[-1]+i)    for j in xrange(Q):        l, r = map(int, input.readline().strip().split())        output.writelines('%s\n'%(get_sum(psum, ss, r, N)-get_sum(psum, ss, l-1, N)))

 

转载于:https://www.cnblogs.com/sherylwang/p/5620780.html

你可能感兴趣的文章
hdu 5471(状压DP or 容斥)
查看>>
oracle.jdbc.driver.OracleDriver和oracle.jdbc.OracleDriver这两个驱动的区别
查看>>
NSQ部署
查看>>
git常用命令记录
查看>>
唯品会HDFS性能挑战和优化实践
查看>>
大厂前端高频面试问题与答案精选
查看>>
我们用5分钟写了一个跨多端项目
查看>>
Visual Studio 15.4发布,新增多平台支持
查看>>
有赞透明多级缓存解决方案(TMC)设计思路
查看>>
如何设计高扩展的在线网页制作平台
查看>>
Git 2.5增加了工作树、改进了三角工作流、性能等诸多方面
查看>>
Swift 5将强制执行内存独占访问
查看>>
中台之上(二):为什么业务架构存在20多年,技术人员还觉得它有点虚?
查看>>
深度揭秘腾讯云低功耗广域物联网LPWAN 技术及应用
查看>>
与Jeff Sutherland谈敏捷领导力
查看>>
More than React(四)HTML也可以静态编译?
查看>>
React Native最佳学习模版- F8 App开源了
查看>>
云服务正在吞噬世界!
查看>>
阅读Android源码的一些姿势
查看>>
Web语义化标准解读
查看>>