• 2019牛客暑期多校训练营(第一场)


    A - Equivalent Prefixes - 单调栈

    题意:给定两个n个元素的数组a,b,它们的前p个元素构成的数组是“等价”的,求p的最大值。“等价”的意思是在其任意一个子区间内的最小值相同。

    考虑使用单调栈去弄它。每次单调栈中的元素会回答以栈顶元素为结尾的区间的最小值是多少。

    比如数组:
    2,4,3,5,1

    前1个元素的单调栈:
    {{2,1}}
    意思是[1,1]的最小值是2

    前2个元素的单调栈:
    {{2,1},{4,2}}
    意思是[1,2]的最小值是2,[2,2]的最小值是4

    前3个元素的单调栈:
    {{2,1},{3,3}}
    意思是[1,3]的最小值是2,[2,3]的最小值是3,[3,3]的最小值是3

    前4个元素的单调栈:
    {{2,1},{3,3},{5,4}}
    意思是[1,4]的最小值是2,[2,4]的最小值是3,[3,4]的最小值是3,[4,4]的最小值是5

    前5个元素的单调栈:
    {{5,1}}
    意思是[x,5]的最小值都是1

    所以每次只需要比较单调栈的大小就可以知道是不是新加的元素可以使得数组保持“等价”。

    要是使用单调队列,那么在新元素入队之前弹空,弹出的时候可以顺便把一系列的区间最值给刷新掉。

    #include<bits/stdc++.h>
    using namespace std;
    
    int a[500005];
    int b[500005];
    
    stack<int> sta, stb;
    
    int main() {
        int n;
        while(~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]);
            }
            int ans = 0;
            for(int i = 1; i <= n; i++) {
                while(!sta.empty() && sta.top() >= a[i])
                    sta.pop();
                sta.push(a[i]);
                while(!stb.empty() && stb.top() >= b[i])
                    stb.pop();
                stb.push(b[i]);
                if(sta.size() != stb.size())
                    break;
                else
                    ans++;
            }
            printf("%d
    ", ans);
            while(!sta.empty())
                sta.pop();
            while(!stb.empty())
                stb.pop();
        }
    }
    

    不用STL会更省内存,但不一定会更快。其实这个算法是在线的,a和b可以不存。

    #include<bits/stdc++.h>
    using namespace std;
    
    int a[500005];
    int b[500005];
    
    int sta[500005], statop;
    int stb[500005], stbtop;
    
    int main() {
        int n;
        while(~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]);
            int ans = 0;
            statop = 0, stbtop = 0;
            for(int i = 1; i <= n; i++) {
                while(statop && sta[statop] >= a[i])
                    statop--;
                sta[++statop] = a[i];
                while(stbtop && stb[stbtop] >= b[i])
                    stbtop--;
                stb[++stbtop] = b[i];
                if(statop != stbtop)
                    break;
                else
                    ans++;
            }
            printf("%d
    ", ans);
        }
    }
    
  • 相关阅读:
    Python常用模块学习
    如何在cmd下切换不同版本的Python
    Python3
    Python第二模块(文件和函数)
    Hibernate教程一览
    struts2框架一览
    Java正式day_04——嵌套循环
    AJAX
    JS+JQUERY
    Mybatis注意问题
  • 原文地址:https://www.cnblogs.com/Yinku/p/11210511.html
Copyright © 2020-2023  润新知