#1044. Shopping in Mars【双指针 + 前缀和】

原题链接

Problem Description:

Shopping in Mars is quite a different experience. The Mars people pay by chained diamonds. Each diamond has a value (in Mars dollars M$). When making the payment, the chain can be cut at any position for only once and some of the diamonds are taken off the chain one by one. Once a diamond is off the chain, it cannot be taken back. For example, if we have a chain of 8 diamonds with values M$3, 2, 1, 5, 4, 6, 8, 7, and we must pay M$15. We may have 3 options:

  1. Cut the chain between 4 and 6, and take off the diamonds from the position 1 to 5 (with values 3+2+1+5+4=15).
  2. Cut before 5 or after 6, and take off the diamonds from the position 4 to 6 (with values 5+4+6=15).
  3. Cut before 8, and take off the diamonds from the position 7 to 8 (with values 8+7=15).

Now given the chain of diamond values and the amount that a customer has to pay, you are supposed to list all the paying options for the customer.

If it is impossible to pay the exact amount, you must suggest solutions with minimum lost.

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 numbers: N N N ( ≤ 1 0 5 \leq 10^5 105), the total number of diamonds on the chain, and M M M ( ≤ 1 0 8 \leq 10^8 108), the amount that the customer has to pay. Then the next line contains N N N positive numbers D 1 ⋯ D N ( D i ≤ 1 0 3 D_1 \cdots D_N (D_i \leq 10^3 D1DN(Di103 for all i = 1 , ⋯   , N i=1,\cdots,N i=1,,N) which are the values of the diamonds. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print i-j in a line for each pair of i ≤ \leq j such that D i + … + D j = M D_i + \ldots + D_j = M Di++Dj=M. Note that if there are more than one solution, all the solutions must be printed in increasing order of i.

If there is no solution, output i-j for pairs of i ≤ \leq j such that D i + … + D j > M D_i + \ldots + D_j > M Di++Dj>M with ( D i + … + D j − M D_i + \ldots + D_j −M Di++DjM) minimized. Again all the solutions must be printed in increasing order of i.

It is guaranteed that the total value of diamonds is sufficient to pay the given amount.

Sample Input 1:

16 15
3 2 1 5 4 6 8 7 16 10 15 11 9 12 14 13

Sample Output 1:

1-5
4-6
7-8
11-11

Sample Input 2:

5 13
2 4 5 7 9

Sample Output 2:

2-4
4-5

Problem Analysis:

由于需要计算随机的区间和,可以先用前缀和预处理一下。

预处理完之后,我们可以按照题目要求用双指针枚举切割位置和区间和。

这里不管枚举左右两边任何一个端点,另一个端点都不需要回溯,原因在于这个序列每个元素都是大于 0 0 0 的,枚举完一个位置后,另一个端点只会保持原位或者向右移动而不可能会向左移动。具体细节见代码。

Code

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10, INF = 1e9;

int n, m;
int s[N];

int main()
{
    
    
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i ++ )
    {
    
    
        scanf("%d", &s[i]);
        s[i] += s[i - 1];
    }
    
    int res = INF;
    for (int i = 0, j = 1; i <= n; i ++ )
    {
    
    
        while (j <= n && s[j] - s[i] < m) j ++ ;  // 如果枚举区间右端点,这里条件中的 j <= n 可以省略
        if (j <= n && s[j] - s[i] >= m) res = min(res, s[j] - s[i]);
    }
    
    for (int i = 0, j = 1; i <= n; i ++ )
    {
    
    
        while (j <= n && s[j] - s[i] < m) j ++ ;
        if (j <= n && s[j] - s[i] == res) printf("%d-%d\n", i + 1, j);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/geraltofrivia123/article/details/121252343