给出一个环,求连续的k个数字中连续和最大是是多少,子串的开始下标和结束坐标是多少。
第一次做这题的时候是在学单调队列的时候,单调队列的做法戳这里
这里我是直接dp搞, dp[i]=sum[i]−min(sum[j])i−k<=j<i
显然直接做复杂度O(nk)是超时的,就用线段树维护一下min(sum[j])就行了。
我在找ansl的时候用lower_bound在sum里面找min(sum[j])的下标不知道为什么WA= =。。后来改成在外面遍历一遍[ansr - k + 1,ansr]才没有WA,然后TLE了。。。我刚开始是每做到一个数就update进去这个i,然后改成直接建树的时候就PushUp了不再update就过了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define LL long long
#define Lowbit(x) ((x)&(-x))
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1|1
#define MP(a, b) make_pair(a, b)
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
const int maxn = 1e5 + 10;
const double eps = 1e-8;
const double PI = acos(-1.0);
typedef pair<int, int> pii;
int a[maxn*2], sum[maxn*2];
int mmin[(maxn*2)<<2];
inline void PushUp(int rt)
{
mmin[rt] = min(mmin[rt<<1], mmin[rt<<1|1]);
}
void build(int l, int r, int rt)
{
if (l == r)
{
mmin[rt] = sum[l];
return ;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
inline void update(int pos, int val, int l, int r, int rt)
{
if (pos <= l && r <= pos)
{
mmin[rt] = val;
return ;
}
int mid = (l + r) >> 1;
if (pos <= mid) update(pos, val, lson);
if (pos > mid) update(pos, val, rson);
PushUp(rt);
}
inline int query(int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R)
{
return mmin[rt];
}
int mid = (l + r) >> 1;
int res = INF;
if (L <= mid) res = min(res, query(L, R, lson));
if (R > mid) res = min(res, query(L, R, rson));
return res;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n, k, T;
scanf("%d", &T);
while (T--){ //T是后加的所以格式丑了点= =
scanf("%d%d", &n, &k);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]), a[i+n] = a[i];
n <<= 1;
memset(sum, 0x3f, sizeof(sum));
memset(mmin, 0x3f, sizeof(mmin));
sum[0] = 0;
for (int i = 1; i <= n; i++)
sum[i] = sum[i-1] + a[i];
build(1, n, 1);
int ans = sum[1], ansl = 1, ansr = 1;
for (int i = 2; i <= n; i++)
{
if (i - k <= 0 && sum[i] - sum[0] > ans)
{
ans = sum[i] - sum[0];
ansl = 1;
ansr = i;
}
int l = max(i - k, 1), r = i - 1;
int minval = query(l, r, 1, n, 1);
//printf("%d %d %d %d\n", l, r+1, minval, sum[i] - minval);
if (sum[i] - minval > ans)
{
ans = sum[i] - minval;
ansr = i;
}
}
for (int i = max(ansr - k + 1, 1); i <= ansr; i++)
if (sum[ansr] - sum[i-1] == ans)
{
ansl = i;
break;
}
if (ansl % (n >> 1) == 0) ansl = (n >> 1);
else ansl %= (n >> 1);
if (ansr % (n >> 1) == 0) ansr = (n >> 1);
else ansr %= (n >> 1);
printf("%d %d %d\n", ans, ansl, ansr);}
return 0;
}