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
思路:
在所有的數裏面,根據他的規則就將數組分成了若干個循環圈。我們只要在每個圈裏找出任意起點能獲得的最大開心值,那麼所有的開心值取個max,最後和s比較就行啦。既然是圈那麼每跑一圈的收穫都是確定的,那麼我們就可以只計算餘數就好了。
可是有這麼一種情況,就是說我們要取得數比餘數多但又小於一個週期。爲了解決這麼一個問題,我們可以把其中一個週期放到餘數一起計算,這樣就會得到最大值啦。然後RMQ來解決最大區間子段和。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf = 1e18;
const int maxn = 1e5+666;
ll a[maxn],b[maxn],dp[maxn][20];
int mk[maxn];
void ST(ll A[],ll n) {
for (int i = 1; i <= n; i++)
dp[i][0] = A[i];
for (int j = 1; (1 << j) <= n; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
}
}
}
ll RMQ(int l, int r) {
int k = (int)(log(double(r-l+1))/log((double)2));
return max(dp[l][k], dp[r - (1 << k) + 1][k]);
}
int main()
{
int t_t,cas = 1;
scanf("%d",&t_t);
while(t_t--)
{
ll n,m,s,k;
scanf("%lld%lld%lld%lld",&n,&s,&m,&k);;
for(int i = 0; i < n; i++)
{
scanf("%lld",&a[i]);
}
memset(mk,0,sizeof(mk));
ll ans = -inf;
for(int i = 0; i < n; i++)
{
if(mk[i]) continue;
int x = i;
int j = 1;
while(!mk[x])
{
mk[x] = 1;
b[j++] = a[x];
x = (x+k)%n;
}
for(int l = 1; l < j; l++)
{
b[l+j-1] = b[l];
b[l+2*j-2] = b[l];
}
b[0] = 0;
for(int l = 1; l <= (j-1)*3; l++)
{
b[l] += b[l-1];
}
ll res = 0;
ll M = m;
ll fasd = 0;
if(m > j-1)
{
M = m-j+1;
fasd = j-1;
}
else M = m;
ll mm = m%(j-1)+fasd;
ST(b,(j-1)*3LL);
ll mx = -inf;
for(int l = 1; l < j; l++)
{
ll mmx = 0;
ll tmp = b[j-1];
if(tmp > 0)
{
mmx += tmp*(M/(j-1));
}
ll ghf = RMQ(l,l+mm-1)-b[l-1];
mmx += ghf;
mx = max(mx,mmx);
}
ans = max(ans,mx);
}
if(ans < 0) ans = s;
else
{
if(s-ans >= 0) ans = s-ans;
else ans = 0;
}
printf("Case #%d: %lld\n",cas++,ans);
}
return 0;
}
/*
10
6 10 5 2
3 -3 2 3 -4 1
*/