C. Manhattan Subarrays(思维)

Problem - C - Codeforces

假设有两点p = (p, yp)和q = (g,yg)。我们把它们之间的曼哈顿距离记为d(p,q) = p-l + yp-yl。如果d(p, r) = d(p, q) + d(q, r)那么p, q, r这三个点组成了一个坏的三元组。假设一个数组b1, b2,, bm是好的,如果它不可能选择三个不同的指标i, j, k,使得这些点和(bk, k)组成一个坏的三元组。(b, i), (b,j)已知一个数组a1, a2,。计算a的好子数组的个数。数组a的子数组是数组al, al+1,。, a,对于某个1 <l<r<n。注意,根据定义,长度为1和2的子数组是好的。输入第一行包含一个整数t (1 <t < 5000)——测试用例的数量。每个测试用例的第一行包含一个整数n (1 <n <2-105)-数组a的长度。每个测试用例的第二行包含n个整数a1, a2,。, an (1 < ai < 10°)。可以保证n的和不超过2 - 105。输出对于每个测试用例,打印数组a的良好子数组的数量。

Example

input

Copy

3
4
2 4 1 3
5
6 9 1 9 6
2
13 37

output

Copy

10
12
3

请注意在第一个测试用例中,可以证明a的任何子数组都是好的。例如,子数组[a2, as, a4]是很好的,因为它只包含三个元素,并且:d((a2, 2), (a4, 4)) = 14-3 +12-4 = 3 < d((a2, 2), (a3, 3)) + d((a3, 3), (a4, 4)) = 3+1+2+1 = 7;d ((a2,(2)、(a3, d (3) < (a2、(2)、(a4, d (4)) + (3) (a3、a4));d ((a3、a4 (3), (4) < d (a3、(3)、(a2) + d ((a4 a2、(2)、(4);例如,在第二个测试用例中,子数组[a1, @2, a3, a4)是不好的,因为它包含了一个坏的三元组(a1, 1), (a2, 2), (a4, 4):d((a1, 1), (a4, 4)) = 16-9|+|1- 4] = 6;d((a1, 1), (a2, 2)) = 16 - 9|+ |1 - 2|= 4;d ((a2、(2)、(4)a4) = 19 - 9 | + 12 - 4] = 2;So, d ((a1, 1), (a4, d (4) = (a1, 1), (a2, (2)) + d ((a4 a2、(2)、(4)。

题解:
遇到越是没有思路的题,越要从题目所给的条件中入手,没有思路,说明是没有读懂题意

看是否能把题目所给条件变形,或换推一下公式

结合题目给我们的式子,我们可以发现

假设i < j < k 三个点值为a , b ,c

x = |a - b| + |i - j|  <=> x = |a - b| + j - i

y = |a - c| + |i - k| <=> y = |a - c| + k - i

z = |b - c| + |j - k|<=>  z = |b - c| + k - j

如果a >= b >= c

x + z = y

如果a <= b <= c

依旧x + z = y

这就是我们所发现的规律

假如子串长度l

l = 1||l = 2,肯定是数组

l = 3如果出现上述情况,就不是好数组了

l = 4 子序列如果能组成上述情况,也不是好数组

l = 5,子序列一定会出现单调不下降,或单调不上升的情况所以一定不是好数组

#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
int a[200050];
int check(int x,int y,int z)
{
	if((x >= y&&y >= z)||(x <= y&&y <= z))
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
void solve()
{
	int n;
	scanf("%d",&n);
	for(int i = 1;i <= n;i++)
	{
		scanf("%d",&a[i]);
	}
	int ans = 2*n - 1;
	if(n >= 3)
	{
		for(int i = 1;i <= n - 2;i ++)
		{
			if(check(a[i],a[i+1],a[i+2]));
			else
			ans++;
		}
	}
	if(n >= 4)
	{
		for(int i = 1;i <= n - 2;i++)
		{
			if(check(a[i],a[i+1],a[i+2])||check(a[i],a[i+1],a[i+3])||check(a[i],a[i+2],a[i+3])||check(a[i+1],a[i+2],a[i+3]));
			else
			ans++;
		}
	}
	printf("%d\n",ans);
}
signed main() 
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);
	int t = 1;
    scanf("%d",&t);
	while (t--) 
	{
		solve();
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值