CF1156E Special Segments of Permutation题解瞎搞 单调栈

Posted chriskkk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1156E Special Segments of Permutation题解瞎搞 单调栈相关的知识,希望对你有一定的参考价值。

题面:http://codeforces.com/contest/1156/problem/E

Luogu翻译:https://www.luogu.com.cn/problem/CF1156E

话说Luogu要改域名了

大意:给定一个长度为n的排列p,求有多少区间[l,r]满足,p[l]+p[r]=maxp[i],其中l<=i<=r

 

据说可以笛卡尔树。

可是我不会

那么就瞎搞。

预处理出左边第一个比a[i]大的数的位置,记为L[i]

R[i]同理为右边。

这个可以用单调栈求。

然后就可以枚举l和r了。

但是显然这样会爆炸。

但是由于题目的限制,可以只枚举一边。

另外一边直接查询有没有。

比如枚举了l,那么p[r]=pmax-p[l]

只用知道右边有没有p[r]就可以了。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2*1e5+10;
int n,a[maxn],pos[maxn];
long long ans;
int L[maxn],R[maxn],s[maxn];
int main()

    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
        pos[a[i]]=i;
    
    int top=0;
    for(int i=1;i<=n;i++)
        while(top && a[s[top]]<a[i]) top--;
        L[i]=s[top];
        s[++top]=i;
    
    top=0;s[top]=n+1;
    for(int i=n;i;i--)
        while(top && a[s[top]]<a[i]) top--;
        R[i]=s[top];
        s[++top]=i;
    
    for(int i=1;i<=n;i++)
        if(i-L[i]<R[i]-i)
            for(int j=L[i]+1;j<i;j++)
                if(pos[a[i]-a[j]]>i && pos[a[i]-a[j]]<R[i]) ans++;
        else
            for(int j=i+1;j<R[i];j++)
                if(pos[a[i]-a[j]]<i && pos[a[i]-a[j]]>L[i]) ans++;
        
    
    printf("%d\n",ans);
    return 0;

 

以上是关于CF1156E Special Segments of Permutation题解瞎搞 单调栈的主要内容,如果未能解决你的问题,请参考以下文章

E. Special Segments of Permutation(双指针&分治)

Codeforces1156 E. Special Segments of Permutation(单调栈,复杂度分析)

Vika and Segments - CF610D

CF1108E1 Array and Segments (Easy version)(待更新)

CF429E Points and Segments

CF429EPoints and Segments 欧拉回路