Max Sum of Max-K-sub-sequence HDU - 3415(单调队列)

单调队列三步:去尾,删头,维护答案。
去尾:从后往前,把不如要加入的点优秀的点删除。
删头:把不在范围的点出队。
这里要维护[i-m,i)范围内的最小前缀和,这样sum[i]-sum[min]可取得每个位置下的最优答案,然后维护最大。

const int N = 2e5 + 5;

int t;
int a[N];
int sum[N];//求每个位置的前缀,比较保留哪个位置
int q[N];
int main()//单调队列解决区间最值
{
	int n, m;
	cin >> t;
	while (t--)
	{
		int tail = 0, head = 0;
		cin >> n >> m;
		sum[0] = 0;
		f(i, 1, n) { scanf("%d", &a[i]);sum[i] = sum[i - 1] + a[i]; }
		f(i, n + 1, n + m-1) { sum[i] = sum[i - 1] + a[i - n]; }
		//f(i, 1, 2 * n)cout << sum[i] << " ";
		ll mx = -2e9, st = 1, ed = 1;
		f(i, 1, n + m-1)//单调增
		{
			while (head <tail && sum[q[tail-1]-1] > sum[i - 1])//维护前缀递增序列
				tail--;//删尾并加入: 删掉比当前大的,因为越后面掌控的范围多。如果前面小的,还应保留
			q[tail++] = i;
			while (head <tail && i - q[head]+1> m)
				head++;//去头,把不在[i-m,i)的老东西弄死
			//在[i-m,i-1]之间最小的前缀,保证求差后的最大
			
			if (mx < sum[i] - sum[q[head]-1])
			{
				mx = sum[i] - sum[q[head]-1];
				st = q[head];
				ed = i;
			}
		}
		if (ed > n)ed -= n;
		cout << mx << " " << st << " " << ed << endl;
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值