Codeforces 1156E Special Segments of Permutation(单调栈)

   可以用单调栈直接维护出ai所能覆盖到的最大的左右范围是什么,然后我们可以用这个范围暴力的去查询这个区间的是否有满足的点对,一个小坑点,要对左右区间的大小进行判断,只需要去枚举距离i最近的一段区间去枚举即可,复杂度On,如果不判断可以退化成n^2。

  10

  1 2 3 4 5 6 7 8 9 10

//      ——By DD_BOND 

//#include<bits/stdc++.h>
#include<functional>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<cstddef>
#include<cstdio>
#include<memory>
#include<vector>
#include<cctype>
#include<string>
#include<cmath>
#include<queue>
#include<deque>
#include<ctime>
#include<stack>
#include<map>
#include<set>

#define fi first
#define se second
#define MP make_pair
#define pb push_back
#define INF 0x3f3f3f3f
#define pi 3.1415926535898
#define lowbit(a)  (a&(-a))
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define Min(a,b,c)  min(a,min(b,c))
#define Max(a,b,c)  max(a,max(b,c))
#define debug(x)  cerr<<#x<<"="<<x<<"\n";

using namespace std;

typedef long long ll;
typedef pair<int,int> P;
typedef pair<ll,ll> Pll;
typedef unsigned long long ull;

const ll LLMAX=2e18;
const int MOD=1e9+7;
const double eps=1e-8;
const int MAXN=1e6+10;

inline ll sqr(ll x){ return x*x; }
inline int sqr(int x){ return x*x; }
inline double sqr(double x){ return x*x; }
ll gcd(ll a,ll b){ return b==0? a: __gcd(b,a%b); }
ll exgcd(ll a,ll b,ll &x,ll &y){ ll d; (b==0? (x=1,y=0,d=a): (d=exgcd(b,a%b,y,x),y-=a/b*x)); return d; }
ll qpow(ll a,ll n){ll sum=1;while(n){if(n&1)sum=sum*a%MOD;a=a*a%MOD;n>>=1;}return sum;}
inline int dcmp(double x){  if(fabs(x)<eps) return 0;   return (x>0? 1: -1); }

int id[MAXN],a[MAXN],l[MAXN],r[MAXN];

int main(void)
{
    ios::sync_with_stdio(false);    cin.tie(0);   cout.tie(0);   
    int n,ans=0;  cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        id[a[i]]=i;
    }
    a[0]=a[n+1]=INF;
    stack<int>q;    q.push(0);
    for(int i=1;i<=n;i++){
        while(a[q.top()]<a[i])    q.pop();
        l[i]=q.top()+1;
        q.push(i);
    }
    while(!q.empty())   q.pop();
    q.push(n+1);
    for(int i=n;i>=1;i--){
        while(a[q.top()]<a[i])    q.pop();
        r[i]=q.top()-1;
        q.push(i);
    }   
    for(int i=1;i<=n;i++){
        if(i-l[i]<r[i]-i){
            for(int j=l[i];j<i;j++)
                if(id[a[i]-a[j]]>i&&id[a[i]-a[j]]<=r[i])
                    ans++;
        }
        else{
            for(int j=i+1;j<=r[i];j++)
                if(id[a[i]-a[j]]<i&&id[a[i]-a[j]]>=l[i])
                    ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/dd-bond/p/10815288.html
今日推荐