HDU6444 Neko's loop

Keywords: less

Problem Description

Neko has a loop of size n.
The loop has a happy value ai on the i−th(0≤i≤n−1) grid.
Neko likes to jump on the loop.She can start at anywhere. If she stands at i−th grid, she will get ai happy value, and she can spend one unit energy to go to ((i+k)modn)−th grid. If she has already visited this grid, she can get happy value again. Neko can choose jump to next grid if she has energy or end at anywhere.
Neko has m unit energies and she wants to achieve at least s happy value.
How much happy value does she need at least before she jumps so that she can get at least s happy value? Please note that the happy value which neko has is a non-negative number initially, but it can become negative number when jumping.

Input

The first line contains only one integer T(T≤50), which indicates the number of test cases.
For each test case, the first line contains four integers n,s,m,k(1≤n≤104,1≤s≤1018,1≤m≤109,1≤k≤n).
The next line contains n integers, the i−th integer is ai−1(−109≤ai−1≤109)

Output

For each test case, output one line "Case #x: y", where x is the case number (starting from 1) and y is the answer.

Sample Input

2
3 10 5 2
3 2 1
5 20 6 3
2 3 2 1 5

Sample Output

Case #1: 0
Case #2: 2

thinking

First of all, there is a cyclic sequence of length nn. Each position of the sequence has a value. When you jump to this position, you will get the integral of the value of this position. You can jump no more than mm times, but every time you have to jump every kk. Now you want to get at least SS integral. Ask how many integrals you need to get plus the product from this cyclic sequence. The sum of points is not less than ss, which is essentially to find the maximum value that can be obtained on this ring.

The test data is given in the form of tt group test data, then four numbers n,s,m,kn,s,m,k are given, and then the next line is the specific value of the nn number.

Firstly, for a ring, it can only take kk step at a time, and there must be a cyclic section. From Peishu Theorem, we can get that the number of cyclic nodes cnt=gcd(n,k)cnt=gcd(n,k), and the length of cyclic nodes len=n/cntlen=n/cnt.

Our first idea is to find the maximum value on each cycle section.

So for each cycle section, how should we maximize it?

For each cycle section, we can jump from any position on the cycle section, and the number of jumps does not exceed mm. So for the current cycle section, we can find a prefix and sum [] array. As long as there is sum [len] > 0 sum [len] > 0, then it proves that no matter which position on the cycle section, no matter which position we start to walk, after walking this cycle section, I can find a prefix and sum [] array. The weight we get must be a positive value.

We can assume that:

  • There are two situations when m >= lenm >= len:

    1. When sum [len] > 0 sum [len] > 0 sum [len] > 0, we will walk as much as possible in this cycle section, and the value we can get is sum[len]*(m/len), at which time the length of m%lenm%len is left untreated. We then deal with the remaining length. First, we build a segment tree to maintain the minimum value of the sum [] array, because we can calculate the sum of any interval from the prefix and (sum[l...r]=sum[r]-sum[l-1]). We already know that the right end of the current interval sum[r], in order to make sum[l-1] as small as possible, so we use the segment tree to find the length of m%lenm%len. Maximum.
    2. In the second case, we divide the length into two intervals. The first one is [1...len], the second one is [len+1...m]. As above, we find that [len+1...m] contains at most several lens, and the result is sum[len]*(M/len). The remaining length is [1...len]. We use the line segment tree to find the maximum value. Then the larger one is found in the two cases.
  • When m<lenm<len:

    This is the first case in which we calculate m%lenm%len and do not need to calculate any more.

Code

#include <bits/stdc++.h>
using namespace std;
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const ll N = 2e5 + 10;
const ll inf = 1e18;
ll n, m, s, k, a[N], b[N], sum[N], cnt, len, MIN[N << 2];
void pushup(ll rt)
{
    MIN[rt] = min(MIN[rt << 1], MIN[rt << 1 | 1]);
}
void build(ll l, ll r, ll rt)
{
    if (l == r)
    {
        MIN[rt] = sum[l];
        return;
    }
    ll m = (l + r) >> 1;
    build(lson);
    build(rson);
    pushup(rt);
}
ll query(ll L, ll R, ll l, ll r, ll rt)
{
    if (L <= l && r <= R)
        return MIN[rt];
    ll m = (l + r) >> 1;
    ll ans = inf;
    if (L <= m)
        ans = min(ans, query(L, R, lson));
    if (R > m)
        ans = min(ans, query(L, R, rson));
    return ans;
}
ll get_max(ll pos)
{
    ll ans = 0, mm = m;
    for (ll i = 1; i <= len; i++)
    {
        b[i] = b[i + len] = a[pos];
        pos = (pos + k) % n;
    }
    for (ll i = 1; i <= 2 * len; i++)
        sum[i] = sum[i - 1] + b[i];
    build(1, 2 * len, 1);
    ll res1 = 0, res2 = 0;
    if (sum[len] > 0)
        res1 = sum[len] * (mm / len);
    mm %= len;
    for (ll i = len + 1; i <= 2 * len; i++)
        res2 = max(res2, sum[i] - query(i - mm, i, 1, 2 * len, 1));
    ans = res1 + res2;
    if (m > len)
    {
        mm = (m - len);
        if (sum[len] > 0)
            res1 = sum[len] * (mm / len);
        mm = len;
        for (ll i = len + 1; i <= 2 * len; i++)
            res2 = max(res2, sum[i] - query(i - mm, i, 1, 2 * len, 1));
        ans = max(ans, res1 + res2);
    }
    return ans;
}
void solve()
{
    scanf("%lld%lld%lld%lld", &n, &s, &m, &k);
    for (ll i = 0; i < n; i++)
        scanf("%lld", &a[i]);
    cnt = __gcd(n, k), len = n / cnt;
    ll ans = 0;
    for (ll i = 0; i < cnt; i++)
        ans = max(ans, get_max(i));
    ans = ans > s ? 0 : s - ans;
    printf("%lld\n", ans);
}
int main()
{
    //freopen("in2.txt", "r", stdin);
    ll t, q = 1;
    scanf("%lld", &t);
    while (t--)
    {
        printf("Case #%lld: ", q++);
        solve();
    }
    return 0;
}

Posted by andrew10181 on Wed, 15 May 2019 22:15:27 -0700