POJ 3320 尺取法 + map + set

当看完书书不同的页所需要经过的最小区间
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <algorithm>
#include <fstream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <ctime>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <deque>
#include <cstdlib>
#include <ctime>
#include <time.h>

inline int Rand (){ return (rand () << 16) | rand ();}
//#define fi first
//#define se second
//#define mp make_pair
//#define sz(x) ( (int) (x).size ())
#define abs(x) ((x) < 0 ? -(x) : (x))
#define INF 20000000000000000ll
//#define sqr(x) ( (x) * (x))
//#define all(x) x.begin (), x.end ()
//#define files(x) freopen (x".in", "r", stdin); freopen (x".out", "w", stdout);
//#define MOD 1000000007
//#define y1 google
#define eps 1e-9
//#define tim ((clock() * 1.0) / CLOCKS_PER_SEC)
#define sf scanf
#define pf printf
#define fup(a,b) for(int i=a;i<=b;i++)
#define fdown(a,b) for(int i=a;i>=b;i--)
#define min(a,b) a>b?b:a
#define max(a,b) a>b?a:b
#define FP freopen("a.txt","r",stdin)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

const int maxn=1000000+20;
ll a[maxn];
set<ll>Save;
map<ll,ll>Map;


int main()
{
	//FP;
	int n;
	while(sf("%d",&n)!=EOF)
	{
		Save.clear();
		Map.clear();
		fup(0,n-1)
		{
			sf("%I64d",&a[i]);
			Save.insert(a[i]);
			//cout<<"Map[a[i]]1:"<<Map[a[i]]<<endl;
		}
		ll l,r,ans,sum,all;
		l=r=0;
		ans=n+1;
		sum=0;                     //表示遍历时遇到的 元素种类
		all=Save.size();
		while(l<=r&&r<n)
		{
			do
			{
				if(Map[a[r++]]++==0)   //当它未加一时候为0说明这种元素之前未访问 sum+1
					++sum;
				//cout<<"Map[a["<<r-1<<"]]R:"<<Map[a[r-1]]<<endl;
			}while(sum<all&&r<n);
			/*cout<<"sum:"<<sum<<endl*/



			do            
			{
				if(--Map[a[l++]]==0)  //当它减一之后为0 说明在这个区间只有一个这种元素 一旦移动 就少一种元素,sum-1
					--sum;              
				//cout<<"Map[a["<<l-1<<"]]L:"<<Map[a[l-1]]<<endl;
			}while(sum==all&&l<=r);

			Map[a[--l]]++;  //左右指针都是超前一位的
			sum++;	//但是右指针超前不影响问题,因为它是冲着sum==all这个目的才向前移动的,并且R超前一格但是L不超前的话,计算区间很方便直接R-L;
			ans=min(ans,r-l);	//左指针是以 sum!=all为目标 才向前移动的 所以要退回去一格
		}
		pf("%I64d\n",ans);

	}
	return 0;
}


#include"set"
#include"map"
#include"iostream"
#include"cstdio"
#define min(a,b) a>b?b:a
#define max(a,b) a>b?a:b
using namespace std;
const int maxn=1000000+10;
int num[maxn];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        set<int>typ;
        for(int i=0;i<n;i++)
        {
            scanf("%d",num+i);typ.insert(num[i]);
        }
        int all=typ.size();
        map<int,int>cnt;
        int sum=0;
        int left=0,right=0;
        int Min=maxn;
        while(right<n+1)
        {
            if(sum==all)
            {
                Min=min(Min,right-left);
                if(cnt[num[left]]-1==0)
                    sum--;
                cnt[num[left]]--;
                left++;
            }
            if(sum<all)
            {
                if(cnt[num[right]]==0)
                  {
                      sum++;
                  }
                cnt[num[right]]++;
                right++;
            }
        }
        printf("%d\n",Min);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值