POJ-3320-Jessica's Reading Problem(尺取法模板)
题目Sample Input
5
1 8 8 8 1
Sample Output
2
给你一个数列,数列中的数可以重复,找出一段区间包含数列中所有的数,求最短区间。
用map维护区间不同数的个数。
//Memory: 2284K Time: 438MS
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<map>
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int N=1e6+2,M=1e5+2,K=17;
int a[N],refl[N],tot,new_id[N];
map<int,int>vis;
int main()
{
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),refl[i]=a[i];
sort(refl+1,refl+n+1);
tot=unique(refl+1,refl+n+1)-(refl+1);
for(int i=1;i<=n;i++)
new_id[i]=lower_bound(refl+1,refl+tot+1,a[i])-refl;
int ans=n,l=1,r=1,num=0;
while(1)
{
while(num<tot&&r<=n)
{
if(!vis[new_id[r]])
++num;
vis[new_id[r]]++;
++r;
}
if(num<tot)
break;
ans=min(ans,r-l);
vis[new_id[l]]--;
if(!vis[new_id[l]])
--num;
l++;
}
printf("%d\n",ans);
}
用主席树维护区间不同数的个数。
//Memory: 42608K Time: 860MS
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<map>
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int N=1e6+5,INF=0x3f3f3f3f;
struct tree{int l,r;}t[N*70];
int root[N],num[N*70],sz;
map<int,int>pos;
void build(int wh,int val,int &x,int y,int l,int r)
{
x=++sz,t[x]=t[y],num[x]=num[y]+val;
if(l==r)
return;
int mid=(l+r)>>1;
if(wh<=mid)
build(wh,val,t[x].l,t[y].l,l,mid);
else
build(wh,val,t[x].r,t[y].r,mid+1,r);
}
int query(int cl,int cr,int x,int l,int r)
{
if(cl<=l&&r<=cr)
return num[x];
int mid=(l+r)>>1,ans=0;
if(cl<=mid)
ans+=query(cl,cr,t[x].l,l,mid);
if(cr>mid)
ans+=query(cl,cr,t[x].r,mid+1,r);
return ans;
}
int main()
{
int n,x;scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);int p=pos[x];
if(!p)
build(i,1,root[i],root[i-1],1,n);
else
{
int tmp=0;
build(p,-1,tmp,root[i-1],1,n);
build(i,1,root[i],tmp,1,n);
}
pos[x]=i;
}
int tot=query(1,n,root[n],1,n);
int ans=n,l=1,r=1,num=0;
while(1)
{
while(num<tot&&r<=n)
{
num=query(l,r,root[r],1,n);
++r;
}
if(num<tot)
break;
ans=min(ans,r-l);
if(r-l>1)
num=query(l+1,r-1,root[r-1],1,n);
else
num=0;
l++;
}
printf("%d\n",ans);
}