zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    
  • 相关阅读:
    TelephonyManager对黑名单的管理
    1125: 零起点学算法32——输出四位完全平方数
    1124: 零起点学算法31——开始新的起程
    1123: 零起点学算法30——参加程序设计竞赛
    1122: 零起点学算法29——等级分制度
    1121: 零起点学算法28——判断是否闰年
    1120: 零起点学算法27——判断是否直角三角形
    1119: 零起点学算法26——判断奇偶数
    1118: 零起点学算法25——求两点之间的距离
    1117: 零起点学算法24——求正弦和余弦
  • 原文地址:https://www.cnblogs.com/Yinku/p/11210511.html
Copyright © 2011-2022 走看看