zoukankan      html  css  js  c++  java
  • 尺取法总结

    最近在做尺取法,总结一下

    尺取法,说白了就是一个st,ed;这两个左右端点(起点、终点)在运动,适用条件就是要求一段连续的区间,

    并且st(左端点)++的时候,一个更优的ed一定要大于或者等于原来的ed

    所以尺取法是一种高效的枚举区间的方法,一般用于求取有一定限制的区间个数或最短的区间等等。

    而且经常与map、set、multiset等连用

    这里推荐几道题:

    1、poj3061

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    int main()
    {
        int n,S;
        int t;
        scanf("%d",&t);
        int a[100005];
        while(t--)
        {
            scanf("%d %d",&n,&S);
            for(int i=0;i<n;i++){
                scanf("%d",&a[i]);
             //printf("%d
    ",sum[i+1]);
            }
    
            int res=n+1;
            int tr=0,s=0,sum=0;
          while1)
           {
               while(tr<n&&sum<S)
               {
                   sum+=a[tr++];
               }
               if(sum<S)break;
              res=min(res,tr-s);
              sum-=a[s++];
           }
           if(res>n)res=0;
           printf("%d
    ",res);
        }
    }
    poj3061

    2、Codeforces Round #333 (Div. 2)

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

    代码:

    这道题结合了multiset

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    #define mod 1000000007
    #define MAX 100005
    int a[MAX];
    int n;
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        multiset<int>s;
        s.clear();
        s.insert(a[1]);
        int Max=a[1],Min=a[1];
        int st=1,ed=1;
        int ans=0;
        for(int i=2;i<=n;i++)
        {
            ed++;
            s.insert(a[i]);
            Max=max(Max,a[i]);
            Min=min(Min,a[i]);
            if(Max-Min<=1)
            ans=max((int)s.size(),ans);
            while(Max-Min>1&&s.size()>0)
            {
                multiset<int>::iterator it;
                it=s.find(a[st]);
                s.erase(it);
                st++;
                multiset<int>::iterator it1=--s.end();
                multiset<int>::iterator it2=s.begin();
                Max=*it1;
                Min=*it2;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    尺取法
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    #define mod 1000000007
    #define INF 0x3f3f3f3f
    #define MAX 100005
    int Max[MAX],Min[MAX];
    int n;
    int a[MAX];
    int lowbit(int x)
    {
        return x&-x;
    }
    void updata(int i,int val)
    {
        while(i<=n){
        Max[i]=max(Max[i],val);
        Min[i]=min(Min[i],val);
        i+=lowbit(i);
        }
    }
    bool query(int l,int r)
    {
        int maxn=a[l],minn=a[r];
        while(1)
        {
            maxn=max(maxn,a[r]),minn=min(minn,a[r]);
            if(l==r) break;
            for(r-=1;r-l>=lowbit(r);r-=lowbit(r))
                maxn=max(Max[r],maxn),minn=min(minn,Min[r]);
        }
        return maxn-minn<=1;
    }
    bool C(int l,int r)
    {
        return query(l,r);
    }
    int main()
    {
        memset(Min,INF,sizeof(Min));
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
          updata(i,a[i]);
       }
       //cout<<query(1,2)<<endl;
        int ans=0;
       for (int i = 1; i <= n; i ++)
        {
            int l = i, r = n;
            while (l <= r)
            {
                int mid = (l + r)/2;
                if (C(i,mid)) l = mid+1;
                else r = mid-1;
            }
            //cout<<l<<r<<ans<<endl;
            ans = max(ans, r - i + 1);
       }
       cout<<ans<<endl;
        return 0;
    }
    树状数组+二分

    3、poj3320

  • 相关阅读:
    windows64系统下安装 redis服务 (详细)
    周期信号的傅里叶级数表示
    LeetCode 36——有效的数独
    LeetCode 3——无重复字符的最长子串
    线性时不变系统的卷积
    信号与系统
    C++ 学习笔记之——输入和输出
    LeetCode 74——搜索二维矩阵
    LeetCode 389——找不同
    LeetCode 2——两数相加
  • 原文地址:https://www.cnblogs.com/zhgyki/p/9568819.html
Copyright © 2011-2022 走看看