uva 1451 Average

这道题很巧妙,根据数据,初步分析复杂度小于等于nlogn  

先给一个解题报告:https://wenku.baidu.com/view/b97cd22d0066f5335a8121a3.html

边界问题

首先注意边界问题:有多个解,优先短,然后优先起点小。

优先短:while (q.size() > 1)循环里面的calk判断必须取等号

优先起点小:由于是从前往后遍历,自然起点小的值先存进去,不用特意判断。

题意: 

思路 

关于上凸点可忽略的证明:

 

最后在下凸点中找到最优解:

#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<math.h>
#include<string>
#include<string.h>
#include<map>
#include<unordered_map>
#include<unordered_set>
#include<set>
#include<stack>
#include<sstream>
using namespace std;

int sum[100005], a[100005], p[100005], ans[2];

int calk(int a, int b, int c, int d) {
	return (sum[a] - sum[b])*(c - d) - (sum[c] - sum[d])*(a - b);
}
 
int main()
{
	int t;
	cin >> t;
	
	while (t--) {
		int n, L;
		cin >> n >> L;
		string s;
		cin >> s;
		sum[0] = 0;
		for (int i = 1; i <= n; i++)
			sum[i] = s[i - 1] - '0' + sum[i - 1];

		deque<int> q;
		ans[0] = 0, ans[1] = L;
		for (int i = L; i <= n; i++)
		{
			int j = i - L;
			while (q.size() >= 2) {
				int a = q[q.size() - 1];
				int b = q[q.size() - 2];
				if (calk(j, a, a, b) <= 0) //等号可取可不取
					q.pop_back();
				else
					break;
			}
			q.push_back(j);
			while (q.size() > 1) {
				int a = q[0];
				int b = q[1];
				if (calk(i, b, i, a) >= 0)//等号必取
					q.pop_front();
				else
					break;
			}
			if (calk(i, q.front(), ans[1], ans[0]) > 0 || (calk(i, q.front(), ans[1], ans[0]) == 0 && i - q.front() < ans[1] - ans[0]))
			{
				ans[0] = q.front();
				ans[1] = i;
			}
		}
		cout << ans[0] + 1 << " " << ans[1] << endl; 
	}

	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值