区间最大值和最小值的绝对值相等,有以下两种情况:
第一种情况:区间中只有同一种数字。这个比较简单,通过简单的for循环向后计数得到。
第二种情况:区间中最大值和最小值为相反数。
第二种情况具体来说,就是最大值1,最小值-1,和最大值2,最小值-2。
考虑如何求解第二种情况。
考虑固定左端点时,如何找合法的右端点:
1. 对于最大值为1最小值-1的情况:右端点需要保证:区间中有1和-1,区间中没有2和-2。这可以通
过维护左端点向后的1/-1/2/-2的初始位置找到。右端点的起始位置为max(下一个1的位置,下一
个-1的位置),结束位置为min(下一个2的位置,下一个-2的位置)
2. 对于最大值为2最小值-2的情况:右端点需要保证:区间中有2和-2。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 5e5 + 10;
const int inf = 0x3f3f3f3f;
ll n, ans, num[maxn];
int nxt[maxn][5];
int startpos, endpos;
// -2 –> 0 // -1 –> 1
// 1 –> 3 // 2 –> 4
int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n;
memset(nxt, 0x3f, sizeof nxt);
for(int i = 1;i <= n; ++i) {
cin >> num[i];
}
ll ret = 1, lst = num[1];
for(int i = 2;i <= n; ++i) {
if(num[i] == lst) ++ret;
else {
ans += ret * (ret + 1) / 2;
ret = 1; lst = num[i];
}
}
ans += ret * (ret + 1) / 2;
for(int i = n;i >= 1; –i) {
for(int j = 0;j <= 4; ++j) nxt[i][j] = nxt[i + 1][j];
nxt[i][num[i] + 2] = i;
int maxpos1 = nxt[i][1 + 2], maxpos2 = nxt[i][2 + 2];
int minpos1 = nxt[i][-1 + 2], minpos2 = nxt[i][-2 + 2];
startpos = max(maxpos2, minpos2); endpos = n + 1;
if(startpos != inf && startpos < endpos) ans += endpos – startpos;
startpos = max(maxpos1, minpos1); endpos = min(min(maxpos2, minpos2), (int)n + 1);
if(startpos != inf && startpos < endpos) ans += endpos – startpos;
}
cout << ans << ‘\n’;
return 0;
}