Codeforces1156E. Special Segments of Permutation
Description
You are given a permutation p of n integers 1, 2, ..., n (a permutation is an array where each element from 1 to n occurs exactly once).
Let's call some subsegment p[l,r] of this permutation special if \(p_l + p_r = \max \limits_{i = l}^{r} p_i\). Please calculate the number of special subsegments.
Input
The first line contains one integer n (\(3 \le n \le 2 \cdot 10^5\)).
The second line contains n integers p1, p2, ..., pn (1≤pi≤n). All these integers are pairwise distinct.
Output
Print the number of special subsegments of the given permutation.
Solution
题目大意就是求区间[l,r]的个数,使得p[l]+p[r]=max(p[x])(x∈[l,r])
考虑枚举这个max
但暴力去做是\(O(n^{2})\)的,无法接受
先预处理每个数的位置(因为每个数是唯一的,所以可以乱搞)
然后我们暴力做出对于每个点可以向左(向右)能扩展到的位置
最后暴力枚举较短的那段,可以因为预处理了位置,所以可以O(1)判断该点对于当前的max是否合法
平均下来应该是O(n)的吧(雾大雾)
Code
#include <cstdio>
#include <algorithm>
#define N 200001
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
int n,i,tot,ans,a[N],bz[N],l[N],r[N],dui[N];
void pd(int x,int y)
{
for (int i=x,pl;i<y;i++)
{
pl=bz[a[y]-a[i]];
if (pl>y && pl<=r[y]) ans++;
}
}
void ps(int x,int y)
{
for (int i=y,pl;i>x;i--)
{
pl=bz[a[x]-a[i]];
if (pl<x && pl>=l[x]) ans++;
}
}
int main()
{
open("Special");
scanf("%d",&n);
for (i=1;i<=n;i++)
{
scanf("%d",&a[i]);
bz[a[i]]=i;
}
for (i=1;i<=n;i++)
{
while (a[dui[tot]]<a[i] && tot) tot--;
l[i]=dui[tot]+1;
dui[++tot]=i;
}
tot=0;dui[0]=n+1;
for (i=n;i>=1;i--)
{
while (a[dui[tot]]<a[i] && tot) tot--;
r[i]=dui[tot]-1;
dui[++tot]=i;
}
for (i=1;i<=n;i++)
if (i-l[i]<r[i]-i) pd(l[i],i);else ps(i,r[i]);
printf("%d",ans);
return 0;
}
如果自己说什麽都做不到而什麽都不去做的话,那就更是什麽都做不到,什麽都不会改变,什麽都不会结束.