题意:给一个1-n的排列, 你需要求出有多少个区间满足a[l] + a[r] = max(a[l] - a[r]);
解题思路
首先记录每个数字的下标
然后用单调栈维护以 a[i] 为最高点的区间
然后枚举 a[i] 区间内较短一侧的数
因为1 - n 排列数值唯一且已经记录了位置, 所以可以 O(1) 的求出 (a[i] - 小区间内数 )是否在右侧区间中, 统计得解
代码:
/*
Zeolim - An AC a day keeps the bug away
*/
//pragma GCC optimize(2)
#include <cstdio>
#include <iostream>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <string>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <sstream>
#include <map>
#include <ctime>
#include <vector>
#include <fstream>
#include <list>
#include <iomanip>
#include <numeric>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
//using namespace __gnu_pbds;
//typedef tree <long long, null_type, less <long long>, rb_tree_tag, tree_order_statistics_node_update> rbtree;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define mp(x, y) make_pair(x, y)
const ld PI = acos(-1.0);
const ld E = exp(1.0);
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 10;
const ll MOD = 1e9 + 7;
int arr[MAXN] = {0};
struct node
{
int l, r, loc;
}pos[MAXN];
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0); cout.tie(0);
//freopen("D://test.in", "r", stdin);
//freopen("D://test.out", "w", stdout);
int n;
cin >> n;
for(int i = 1; i <= n; ++i)
cin >> arr[i], pos[i].l = i, pos[i].r = i, pos[arr[i]].loc = i;
stack <int> ST;
arr[0] = arr[n + 1] = INF;
ST.push(0);
for(int i = 1; i <= n; ++i) //单调栈求区间
{
while(!ST.empty() && arr[i] > arr[ST.top()]) ST.pop();
pos[i].l = ST.top() + 1;
ST.push(i);
}
while(!ST.empty()) ST.pop();
ST.push(n + 1);
for(int i = n; i >= 1; --i)
{
while(!ST.empty() && arr[i] > arr[ST.top()]) ST.pop();
pos[i].r = ST.top() - 1;
ST.push(i);
}
int ans = 0;
for(int i = 1; i <= n; ++i)
{
if(i - pos[i].l <= pos[i].r - i)
{
for(int j = pos[i].l; j < i; ++j) //枚举合法
if(pos[arr[i] - arr[j]].loc > i && pos[arr[i] - arr[j]].loc <= pos[i].r)
++ans;
}
else
{
for(int j = i + 1; j <= pos[i].r; ++j)
if(pos[arr[i] - arr[j]].loc < i && pos[arr[i] - arr[j]].loc >= pos[i].l)
++ans;
}
}
cout << ans << '
';
return 0;
}