zoukankan      html  css  js  c++  java
  • 尺取法(滑窗,双指针)

    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);
    }

     
    
    
    
     
     
    
    
    




     
  • 相关阅读:
    在bindingNavigator1中加入具有更好体验性的DateTimePicker
    static的初始化顺序 (转)
    C#数据结构求最大公约数和最小公倍数[辗转相除法]
    DataGridView控件显示行号
    C# 小票打印机 直接打印 无需驱动[转]
    Core Data 中遇到的一些问题
    字符指针不分配存储区,字符常量存储于静态数据区
    传送门
    Error Set
    实现类似iPhone通讯录新增名片,保存,之后可进行编辑操作的功能
  • 原文地址:https://www.cnblogs.com/sweetlittlebaby/p/12601784.html
Copyright © 2011-2022 走看看