/*
translation:
给定一个01数列,选择一个长度至少为L的字串,使得子序列中数字的平均值最大。输出这个子序列的起点和终点
位置
solution:
详见论文"浅谈数型结合思想在信息学竞赛中的应用"
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 100000 + 5;
int sum[maxn], l, r, ans, L, n;
inline double calculate(int s, int e)
{
return (sum[e] - sum[s]) * 1.0 / (e - s);
}
int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &L);
char str[maxn];
scanf("%s", str + 1);
memset(sum, 0, sizeof(sum));
for(int i = 1; i <= n; i++) {
sum[i] = sum[i-1] + str[i] - '0';
}
int l = 0, r = L, len = 0; double ans = 0;
int front_ = 0; int rear_ = 0;
int que[maxn]; memset(que, 0, sizeof(que));
for(int ed = L; ed <= n; ed++) {
int st = ed - L;
while(rear_ > front_ && calculate(que[rear_], st) <= calculate(que[rear_-1], st))
rear_--;
que[++rear_] = st;
while(rear_ > front_ && calculate(que[front_], ed) <= calculate(que[front_+1], ed))
front_++;
double tmp = calculate(que[front_], ed);
if(tmp > ans) {
ans = tmp;
l = que[front_];
r = ed;
len = r - l;
}
else if(tmp == ans && ed - que[front_] < len) {
l = que[front_];
r = ed;
len = ed - que[front_];
}
}
printf("%d %d\n", l + 1, r);
}
return 0;
}
la4276(*数形结合,单调队列求点集斜率极值)
最新推荐文章于 2019-03-09 18:16:52 发布