uva1451

题意:给定一个长度为n的01串,选一个长度至少为L的连续子串,使得子串平均值最大,如果多解,子串长度应尽量小,如果仍多解,起点编号尽量小。

分析:用了数形结合的思想,将平均值的变化用斜率表示出来,找到斜率最大的点。

作者代码:

#include<cstdio>

using namespace std;



const int maxn = 100000 + 5;



int n, L;

char s[maxn];

int sum[maxn], p[maxn]; // average of i~j is (sum[j]-sum[i-1])/(j-i+1)



// compare average of x1~x2 and x3~x4

int compare_average(int x1, int x2, int x3, int x4) {

	return (sum[x2] - sum[x1 - 1]) * (x4 - x3 + 1) - (sum[x4] - sum[x3 - 1]) * (x2 - x1 + 1);

}



int main() {

	int T;

	scanf("%d", &T);



	while (T--) {

		scanf("%d%d%s", &n, &L, s + 1);



		sum[0] = 0;

		for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + s[i] - '0';



		int ansL = 1, ansR = L;



		// p[i..j) is the sequence of candidate start points

		int i = 0, j = 0;

		for (int t = L; t <= n; t++) { // end point

			while (j - i > 1 && compare_average(p[j - 2], t - L, p[j - 1], t - L) >= 0) j--; // remove concave points

			p[j++] = t - L + 1; // new candidate
			while (j - i > 1 && compare_average(p[i], t, p[i + 1], t) <= 0) i++; // update tangent point//找到凸点
			// compare and update solution
			int c = compare_average(p[i], t, ansL, ansR);

			if (c > 0 || c == 0 && t - p[i] < ansR - ansL) {//比较结果点长度越短优先

				ansL = p[i]; ansR = t;

			}

		}

		printf("%d %d\n", ansL, ansR);

	}

	return 0;

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值