zoukankan      html  css  js  c++  java
  • Special Segments of Permutation

    题意

    给定一个全排列(a)

    定义子区间([l,r]),当且仅当(a_l + a_r = Max[l,r])

    (a)序列中子区间的个数。

    题解

    笛卡尔树上的启发式合并。

    (2000MS)的时限,(1965MS)卡过。。

    还可以不建树,直接枚举区间,就可以用数组维护了。这种做法比较快。

    代码

    #include <bits/stdc++.h>
    
    #define FOPI freopen("in.txt", "r", stdin)
    #define FOPO freopen("out.txt", "w", stdout)
    
    using namespace std;
    typedef long long LL;
    const int maxn = 2e5 + 100;
    
    
    int n;
    int a[maxn];
    int ch[maxn][2], fa[maxn];
    map<int, int> M[maxn];
    LL ans = 0;
    
    void build_Dkr()
    {
        stack<int> ST;
        int tmp;
    
        for (int i = 1; i <= n; i++) {
            if (!ST.empty() && a[ST.top()] < a[i]) {
                while(!ST.empty() && a[ST.top()] < a[i]) {
                    tmp = ST.top();
                    ST.pop();
                }
                ch[i][0] = tmp;
                fa[tmp] = i;
            }
    
            if (!ST.empty()) {
                ch[ST.top()][1] = i;
                fa[i] = ST.top();
            }
            ST.push(i);
        }
    }
    
    void merge(int x, int y, int Max)
    {
        if (M[x].size() < M[y].size())
            swap(M[x], M[y]);
    
        for (auto val : M[y]) {
            int a = val.first, b = val.second;
            ans += 1ll * b * M[x][Max-a];
        }
    
        for (auto val : M[y]) {
            int a = val.first, b = val.second;
            M[x][a] += b;
        }
    
        M[y].clear();
    }
    
    void dfs(int x)
    {
        for (int i = 0; i < 2; i++) {
            if (ch[x][i] == 0) continue;
            dfs(ch[x][i]);
            merge(x, ch[x][i], a[x]);
        }
    }
    
    int main()
    {
    //    FOPI;
    
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            M[i][a[i]] = 1;
        }
    
        build_Dkr();
    
        for (int i = 1; i <= n; i++) {
            if (fa[i] == 0) {
                dfs(i);
                break;
            }
        }
    
        printf("%lld
    ", ans);
    }
    
    
  • 相关阅读:
    RabbitMQ之六种队列模式
    面试资料
    位掩码的介绍与使用(小白鼠试毒问题)
    递归函数的写法(以strcpy函数为例)
    查找算法简介及实现
    八大排序算法概述及实现
    快速排序算法(一)
    最大(小)堆和堆排序简介
    满二叉树各种节点数目的计算
    LPSTR、LPCSTR、LPWSTR、LPCWSTR、LPTSTR、LPCTSTR的来源及意义
  • 原文地址:https://www.cnblogs.com/ruthank/p/10910373.html
Copyright © 2011-2022 走看看