• #333 Div2 Problem B Approximating a Constant Range (尺取 && RMQ || 尺取 && multiset)


    题目链接:http://codeforces.com/contest/602/problem/B

    题意 :给出一个含有 n 个数的区间,要求找出一个最大的连续子区间使得这个子区间的最大值和最小值的差值不超过 1 ,最后输出这个子区间的长度。

     

    分析 :我们可以根据区间的最值之差利用尺取的方法来找出答案=> if(差值>1) Left++; else Right++; 然后每一次右端点+1就更新一次答案直到右端点到达 n 。在这里我们需要找出区间最值,也就是经典的RMQ问题,可以利用ST算法模板进行O(nlogn)的预处理接下来进行尺取便不会超时。上述的过程完全可以使用multiset来替代,我们可以每一次把(Left, Right)区间内的数放到multiset里面,根据set容器的特性,我们能很方便得到(Left, Right)这个区间的最值,也能使用erase()在区间不满足题意进行Left++操作时将原来Left的元素在集合内剔除,也能用size()方便的得到区间的长度,但是两者都用到了尺取的思想。

     

    瞎想 :当需要维护区间的时候需要获取最值或者获取区间长度的时候,不妨考虑能否借助set容器来实现。

    Two pointers && RMQ :

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn = 100010;
    int arr[maxn], Max[maxn][18], Min[maxn][18];
    inline void initialize(int & n)
    {
        for(int i=1; i<=n; i++) Max[i][0] = arr[i], Min[i][0] = arr[i];
        for(int j=1; j<18; j++){
            for(int i=1; i<=n; i++){
                if(i + (1<<j) - 1 <= n){
                    Min[i][j] = min(Min[i][j-1], Min[i+(1<<(j-1))][j-1]);
                    Max[i][j] = max(Max[i][j-1], Max[i+(1<<(j-1))][j-1]);
                }
            }
        }
    }
    int RMQ(int L, int R)
    {
        int k = 0;
        //while((1<<(k+1)) <= R-L+1) k++;
        k = log2(R-L+1);
        int MAX = max(Max[L][k], Max[R-(1<<k)+1][k]);
        int MIN = min(Min[L][k], Min[R-(1<<k)+1][k]);
        return MAX - MIN;
    }
    int main(void)
    {
        int n;
        scanf("%d", &n);
        for(int i=1; i<=n; i++) scanf("%d", &arr[i]);
        initialize(n);
        int L = 1, R = 1;
        int ans = 1;
        while(R <= n){
            int temp = RMQ(L, R);
            if(temp <= 1){
                ans = max(R-L+1, ans);
                R++;
            }
            else{
                L++;
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    View Code

    Two pointers && multiset :

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 100001;
    int arr[maxn];
    int main(void)
    {
        int n;
        scanf("%d", &n);
        for(int i=1; i<=n; i++) scanf("%d", &arr[i]);
        multiset<int> s;
        s.insert(arr[1]);
        int Max = arr[1];
        int Min = arr[1];
        int st = 1, ed = 1;//双指针记录Left 和 Right
        int ans = 0;
        for(int i=2; i<=n; i++){
            Max = max(Max, arr[i]);
            Min = min(Min, arr[i]);
            s.insert(arr[i]);
            if(Max - Min <= 1){
                ans = max(ans, (int)s.size());
            }else{
                while(s.size()>0 && Max - Min > 1){//相当于Left++操作
                    set<int>::iterator it = s.find(arr[st]);
                    s.erase(it);
                    st++;
                    set<int>::iterator it_Max = --s.end();
                    set<int>::iterator it_Min = s.begin();
                    Max = *it_Max;
                    Min = *it_Min;
                }
                ans = max(ans, (int)s.size());
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    OpenGL, Net 2005, error C2381: 'exit' : redefinition; __declspec(noreturn) differs
    24点游戏
    一个3*3的格子,给定n>=10, 将[1,n]中的数填入方格中,使得相邻方格的数的和为质数
    最大子矩阵问题 PKU 1050
    12年9月12日
    再谈MSDN Library For Visual Studio 2010
    漫谈.NET开发中的字符串编码
    《.NET 4.0网络开发入门之旅》4:与Socket的第一次“约会”
    “.NET 4.0 网络开发入门之旅系列文章”—— IP 知多少?(下)
    C#之int挑战Java之Integer
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7069863.html
Copyright © 2020-2023  润新知