zoukankan      html  css  js  c++  java
  • Codeforces Round #361 (Div. 2) D

    题目大意:给你两个长度为n的数组a, b,问你有多少个问你有多少个区间满足

    a中最大值等于b中最小值。

    思路:我本来的想法是用单调栈求出每个点的管辖区间,然后问题就变成了巨麻烦的线段覆盖问题,就爆炸写了

    一晚上假算法。正解就是枚举一个端点,然后二分找右端点的区间,因为满足一个很神奇的单调性,然后st表维护

    一下区间最值就好了。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int, int>
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int M = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 420047;
    
    int n, a[N], b[N], bin[20], Log[N], mx[20][N], mn[20][N];
    
    void calRmq() {
        bin[0] = 1; Log[0] = -1;
        for(int i = 1; i < 20; i++) bin[i] = bin[i - 1] * 2;
        for(int i = 1; i < N; i++)  Log[i] = Log[i / 2] + 1;
    
        for(int i = 1; i <= n; i++) mx[0][i] = a[i];
        for(int i = 1; i <= n; i++) mn[0][i] = b[i];
    
        for(int i = 1; i <= Log[n]; i++) {
            for(int j = 1; j <= n; j++) {
                if(j + bin[i] - 1 <= n) {
                    mn[i][j] = min(mn[i - 1][j], mn[i - 1][j + bin[i - 1]]);
                    mx[i][j] = max(mx[i - 1][j], mx[i - 1][j + bin[i - 1]]);
                }
            }
        }
    }
    
    int getVal(int x, int y, int op) {
        int t = Log[y - x + 1];
        if(op) return max(mx[t][x], mx[t][y - bin[t] + 1]);
        return min(mn[t][x], mn[t][y - bin[t] + 1]);
    }
    
    int main(){
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        for(int i = 1; i <= n; i++) {
            scanf("%d", &b[i]);
        }
    
        calRmq();
    
        LL ans = 0;
        for(int i = 1; i <= n; i++) {
            int l = i, r = n, mid, ret1 = -1, ret2 = -1;
            while(l <= r) {
                mid = l + r >> 1;
                int valMin = getVal(i, mid, 0);
                int valMx = getVal(i, mid, 1);
                if(valMin > valMx) l = mid + 1;
                else if(valMin < valMx) r = mid - 1;
                else ret1 = mid, r = mid - 1;
            }
    
    
            l = i, r = n;
            while(l <= r) {
                mid = l + r >> 1;
                int valMin = getVal(i, mid, 0);
                int valMx = getVal(i, mid, 1);
                if(valMin > valMx) l = mid + 1;
                else if(valMin < valMx) r = mid - 1;
                else ret2 = mid, l = mid + 1;
            }
    
            if(ret1 != -1) {
                ans += ret2 - ret1 + 1;
            }
        }
    
        printf("%lld
    ", ans);
        return 0;
    }
    
    /*
    */
    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int, int>
    
    using namespace std;
    
    const int N = 1e5;
    const int M = 1e6 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 +7;
    
    int mm[N];
    struct ST
    {
        int dp[N][20],ty;
        void build(int n,int b[],int _ty)
        {
            ty=_ty;
            for(int i=1;i<=n;i++)
                dp[i][0]=ty*b[i];
            for(int j=1;j<=mm[n];j++)
                for(int i=1;i+(1<<j)-1<=n;i++)
                    dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
        }
        int query(int x,int y)
        {
            int k=mm[y-x+1];
            return ty*max(dp[x][k],dp[y-(1<<k)+1][k]);
        }
    }rmq;
    
    int a[N];
    int main() {
    
        for(int i=-(mm[0]=-1);i<N;i++)
            mm[i]=mm[i-1]+((i&(i-1))==0);
    
        int n; scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
        }
        rmq.build(n, a, 1);
    
        while(1) {
            int x, y; scanf("%d%d", &x, &y);
            cout << rmq.query(x, y) << endl;
        }
        return 0;
    }

    还有一个很神奇的st表

  • 相关阅读:
    问题2 机器学习篇 正则化L1和L2有什么区别?
    numpy 数组拼接方法
    问题1 机器学习篇 如何解决过拟合(overfiting)?
    低阶 TensorFlow 基础知识
    k-Nearest Neighbors 实战2 使用kNN算法改进约会网站的配对结果
    k-Nearest Neighbors 实战1 简单的电影分类实例
    VirtualBox使用
    知乎登录设计思考
    微信返回上一页停留在上次点击的位置
    好的网站-一直在收集
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9233358.html
Copyright © 2011-2022 走看看