Educational Codeforces Round 111 (Rated for Div. 2) C. Manhattan Subarrays(思维/暴力/好题)
Suppose you have two points 𝑝=(𝑥𝑝,𝑦𝑝)p=(xp,yp) and 𝑞=(𝑥𝑞,𝑦𝑞)q=(xq,yq). Let's denote the Manhattan distance between them as 𝑑(𝑝,𝑞)=|𝑥𝑝−𝑥𝑞|+|𝑦𝑝−𝑦𝑞|d(p,q)=|xp−xq|+|yp−yq|.
Let's say that three points 𝑝p, 𝑞q, 𝑟r form a bad triple if 𝑑(𝑝,𝑟)=𝑑(𝑝,𝑞)+𝑑(𝑞,𝑟)d(p,r)=d(p,q)+d(q,r).
Let's say that an array 𝑏1,𝑏2,…,𝑏𝑚b1,b2,…,bm is good if it is impossible to choose three distinct indices 𝑖i, 𝑗j, 𝑘k such that the points (𝑏𝑖,𝑖)(bi,i), (𝑏𝑗,𝑗)(bj,j)and (𝑏𝑘,𝑘)(bk,k) form a bad triple.
You are given an array 𝑎1,𝑎2,…,𝑎𝑛a1,a2,…,an. Calculate the number of good subarrays of 𝑎a. A subarray of the array 𝑎a is the array 𝑎𝑙,𝑎𝑙+1,…,𝑎𝑟al,al+1,…,arfor some 1≤𝑙≤𝑟≤𝑛1≤l≤r≤n.
Note that, according to the definition, subarrays of length 11 and 22 are good.
Input
The first line contains one integer 𝑡t (1≤𝑡≤50001≤t≤5000) — the number of test cases.
The first line of each test case contains one integer 𝑛n (1≤𝑛≤2⋅1051≤n≤2⋅105) — the length of array 𝑎a.
The second line of each test case contains 𝑛n integers 𝑎1,𝑎2,…,𝑎𝑛a1,a2,…,an (1≤𝑎𝑖≤1091≤ai≤109).
It's guaranteed that the sum of 𝑛n doesn't exceed 2⋅1052⋅105.
Output
For each test case, print the number of good subarrays of array 𝑎a.
Example
input
Copy
3
4
2 4 1 3
5
6 9 1 9 6
2
13 37
output
Copy
10
12
3
我是脑瘫。。。想了半天不知道怎么维护,其实显然好序列最长只能为4,然后直接暴力即可。其实题目没要求模也可以知道答案最后不会很大。
证明:
等价于证明任何长度大于等于5的序列中必定含有长度大于等于3的单调不降/不增子序列,只需要证明长度为5的序列成立即可,显然成立(枚举下最大和最小的位置即可)。
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, a[200005];
int judge(int l, int r) {
if(r - l == 2) {//len == 3
if(a[r] >= a[r - 1] && a[r - 1] >= a[r - 2] || a[r] <= a[r - 1] && a[r - 1] <= a[r - 2]) return 0;
else return 1;
} else {//len == 4
if(
a[r] >= a[r - 1] && a[r - 1] >= a[r - 2] || a[r] <= a[r - 1] && a[r - 1] <= a[r - 2] ||
a[r] >= a[r - 1] && a[r - 1] >= a[r - 3] || a[r] <= a[r - 1] && a[r - 1] <= a[r - 3] ||
a[r] >= a[r - 2] && a[r - 2] >= a[r - 3] || a[r] <= a[r - 2] && a[r - 2] <= a[r - 3] ||
a[r - 1] >= a[r - 2] && a[r - 2] >= a[r - 3] || a[r - 1] <= a[r - 2] && a[r - 2] <= a[r - 3]
) return 0;
else return 1;
}
}
signed main() {
int t;
cin >> t;
while(t--) {
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a[i];
}
int ans = 0;
for(int i = 1; i <= n; i++) {
for(int j = i; j <= min(i + 3, n); j++) {
//判断左端点为i,右端点为j的区间是否为好区间
if(j - i <= 1) ans++;
else ans += judge(i, j);
}
}
cout << ans << endl;
}
return 0;
}