尺取法(滑窗,双指针)

poj3061

尺取法裸题,维护动态数组即可 ,l,r,sum,ans;

代码:

#include <cstdio>  
#include <algorithm>  
#include <cstring>  
#define MAX 100005  
#define LL long long  
#define INF 0x3f3f3f3f  
  
using namespace std;  
LL a[100010];  
int n, t, ans = INF;  
LL sum, s;  
  
int main()  
{  
    scanf("%d", &t);  
    while (t--){  
        scanf("%d %I64d", &n, &s);  
        for (int i = 0; i < n; i++) scanf("%I64d", a+i);  
        int l = 0, r = 0;  
        ans = INF; sum = 0;  
        while (1){  
            while (r<n && sum<s) sum += a[r++];  
            if (sum < s) break;  
            ans = min(ans, r-l);  
            sum -= a[l++];  
        }  
        if (ans == INF) ans = 0;  
        printf("%d
", ans);  
    }  
    return 0;
}


poj3320:
这个题理解题意有点难,
主要就是说,找一段连续区间让此区间覆盖所有的不同的a[i];
(map+set+尺取)
代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
typedef long long LL;
using namespace std;
const int inf=0x3f3f3f;
const int maxn = 1000010;

int a[maxn];
map<int ,int> mp;
set<int> s;

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
    {
        scanf("%d",&a[i]);
        s.insert(a[i]);
    }
    int m=s.size();
    int l=0,r=0,ans=inf,sum=0;
    while(1)
    {
        while(r<n&&sum<m)
            {
            if(mp[a[r++]]++==0)
              sum++;
              }
        //cout<<sum<<" "<<r<<endl;
        //for(map<int,int>::iterator it=mp.begin(); it!=mp.end(); it++)
            //cout<<it->first<<" "<<it->second<<endl;
        if(sum<m) break;
        ans=min(ans,r-l);
        if(--mp[a[l++]]==0) sum--;
    }
    printf("%d
",ans);
    return 0;
}
codeforces 616 d(E5)(尺取法+set)map也可以
找不同数字不超过k个的最长连续区间,双指针维护;
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000010;
int n,k;
int a[maxn],f[maxn];
set<int> s;
int main()
{
    cin>>n>>k;
    for(int i=1; i<=n; i++)
     cin>>a[i];
    int ans=0,ansl,ansr,l=1,r=0;
    int mx=0;
    while(l<=n&&r<=n)
    {
        if(s.size()<=k)
        {
            if(mx<r-l+1)
            {
                mx=r-l+1;
                ansl=l;
                ansr=r;
            }
        }
        if(s.size()>k)
        {
            while(s.size()>k)
            {
                f[a[l]]--;
                if(f[a[l]]<=0)
                {
                    s.erase(a[l]);
                }
                l++;
            }
        }
        else
        {
          f[a[++r]]++;//必须是++r,如果r++,更新区间时会出错;
          s.insert(a[r]);
        }    
    }
    printf("%d %d",ansl,ansr);
}
map版本:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1000010;
int n,k;
int a[maxn],f[maxn];
map<int,int> mp;
int main()
{
    cin>>n>>k;
    for(int i=1; i<=n; i++)
     cin>>a[i];
    int ans=0,ansl,ansr,l=1,r=0;
    int mx=0;
    while(l<=n&&r<=n)
    {
        if(mp.size()<=k)
        {
            if(mx<r-l+1)
            {
                mx=r-l+1;
                ansl=l;
                ansr=r;
            }
        }
        if(mp.size()>k)
        {
            while(mp.size()>k)
            {
                mp[a[l]]--;
                if(mp[a[l]]<=0)
                {
                    mp.erase(a[l]);
                }
                l++;
            }
        }
        else
        {
          mp[a[++r]]++;
          //mp.insert(a[r]);
        }    
    }
    printf("%d %d",ansl,ansr);
}

 


 
 






 
原文地址:https://www.cnblogs.com/sweetlittlebaby/p/12601784.html