zoukankan      html  css  js  c++  java
  • Codeforces 1156E Special Segments of Permutation(启发式合并)

    题意:

    给一个n的排列,求满足a[l]+a[r]=max(l,r)的(l,r)对数,max(l,r)指的是l到r之间的最大a[p]

    n<=2e5

    思路:

    先用单调栈处理出每个点能扩展的l[i],r[i]

    搜索以每个点为最大值时的贡献,对每个点只搜索它左边部分或右边部分最小的那个

    可以证明,每个点最多被搜到logn次,类似于启发式合并的思想,

    复杂度为nlogn

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
    #define lowbit(x) ((x)&(-x)) 
    #define LLONG_MAX 9223372036854775807
    
    using namespace std;
    
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef long long LL;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    
    const db eps = 1e-6;
    const int mod = 1e9+7;
    const int maxn = 2e6+11;
    const int maxm = 1e5+100;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    int a[maxn];
    int l[maxn],r[maxn];
    int idx[maxn];
    ll ans = 0;
    void gao(int x){
        int L,R;
        int pL,pR;
        if(x-l[x]<r[x]-x){
            L=l[x];
            R=x-1;
            pL=x+1;
            pR=r[x];
        }
        else{
            pL=l[x];
            pR=x-1;
            L=x+1;
            R=r[x];
        }
        for(int i = L; i <= R; i++){
            int y = a[x]-a[i];
            if(idx[y]>=pL&&idx[y]<=pR)ans++;
        }
    }
    int main(){
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
            idx[a[i]]=i;
            l[i] = r[i] = i;
        }
        a[0]=a[n+1]=n+1;
        for(int i = 1; i <= n; i++){
            while(a[l[i]-1] <= a[i]){
                l[i] = l[l[i]-1];
            }
        }
        for(int i = n; i >= 1; i--){
            while(a[r[i]+1] <= a[i]){
                r[i] = r[r[i]+1];
            }
        }
        ans = 0;
        for(int i = 1; i <= n; i++){
            gao(i);
        }
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    中介者模式(Mediator Pattern)
    状态模式
    命令模式(Command Pattern)
    迭代器模式(Iterator Pattern)
    解释器模式
    备忘录模式
    访问者模式(Visitor Patten)
    责任链模式(chainOfResponsibility)
    .net下安装 ZooKeeper.Net
    Zookeeper .Net客户端代码
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10809082.html
Copyright © 2011-2022 走看看