D. Speedbreaker Codeforces Round 975 (Div. 2)

 原题

D. Speedbreaker

 

解析

这道题题意就是要找出来有多少个起点, 可以每次向左或者右扩展一个城市, 对每个城市在时间 t 到达 a[i] 前扩展到第 i 个城市

双指针来做, l 为左边界, r 为右边界, 只要有一个边界的值大于等于长度, 就缩短边界, 每次检查时更新可取的起点区域(ll, rr)

如果有可以成功的起点, 那么这种起点的数目就是 rr - ll + 1

代码 

#include <bits/stdc++.h>
#define int long long

using namespace std;

const int N = 200010;

int n, m, k, q, ans;

int a[N];

void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i ++ )
	{
		cin >> a[i];
	}
	
	int l = 1, r = n, ll = 1, rr = n;
	
	int ans = 0;
	
	while (l <= r)
	{
		int len = r - l + 1;
		
//      起点要在a[l] - 1步内到达 l, 以下也是同理
		ll = max(ll, l - a[l] + 1);
		ll = max(ll, r - a[r] + 1);
		rr = min(rr, l + a[l] - 1);
		rr = min(rr, r + a[r] - 1);
		
		if (a[l] >= len && a[r] >= len)
		{
			l ++ ;
			r -- ;
		}
		else if (a[l] >= len)
		{
			l ++ ;
		}
		else if (a[r] >= len)
		{
			r -- ;
		}
		else
		{
			cout << 0 << "\n";
			return;
		}
	}
	
	cout << max(0ll, rr - ll + 1) << "\n";
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int T = 1;
	cin >> T;
	while (T -- )
	{
		solve();
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值