【UOJ 578】收集卡片
【题目描述】:
Star计划订购一本将要发行的周刊杂志,但他可不是为了读书而是集卡。
已知杂志将要发行N周(也就是N期),每期都会附赠一张卡片。Star通过种种途径,了解到N期杂志附赠的卡片种类。Star只想订购连续的若干期, 并在这些期内收集到所有可能出现的种类的卡片。现在他想知道,最少需要订 购多少期。
【输入描述】:
第一行一个整数 N;
第二行一个长度为 N 的字符串,由大写或小写字母组成,第 i 个字符表示第i 期附赠的卡片种类,每种字符(区分大小写)表示一种卡片。
【输出描述】:
输出一行一个整数,表示 Star 最少订购的期数。
【样例输入】:
8
acbbbcca
【样例输出】:
3
【样例说明】:
【时间限制、数据范围及描述】:
时间:1s 空间:256M
对于 30%的数据,N≤300;
对于 40%的数据,N≤2000;
对于 60%的数据,N≤5000;
对于 80%的数据,N≤100000;
对于100%的数据,N≤500000。
题解:搞了半天原来是二分出了问题,换了种二分就能过了,开心。
考试的时候80,怎么也想不通,唉。
#include<bits/stdc++.h> #include<iostream> #include<algorithm> #include<queue> #include<cmath> #include<cstring> #include<cstdlib> #include<cstdio> using namespace std; const int N=500002; char s[N],c; bool f[66]; int v[66]; int n,a[N],m,bili; int Yao_Chen(int len){ //for(int l=m;l<=n;l++){ memset(v,0,sizeof(v)); int now=0; for(int i=1;i<=len;i++){ if(v[a[i]]==0) now++; v[a[i]]++; } //if(l==6) cout<<v[27]<<' '<<v[28]<<' '<<now<<endl; if(now==m) return 1;//return l; /*for(int i=2;i<=n-m+1;i++){ if(--v[a[i-1]]==0) now--; if(++v[a[i+len-1]]==1) now++; //if(l==6) cout<<v[27]<<' '<<v[28]<<' '<<now<<endl; if(now==m) return 1;//return l; }*/ for(int i=len+1;i<=n;i++){ //--b[a[i-u]]; if(--v[a[i-len]]==0) --now; //++b[a[i]]; if(++v[a[i]]==1) ++now; if(now==m) return 1; } //} return 0; } int work(){ int l=m,r=n,mid,jj; while(l<=r){ mid=(l+r)/2; //bili=Yao_Chen(mid); if(Yao_Chen(mid)) { r=mid-1; jj=mid; } else l=mid+1; } return jj; } void init(){ scanf("%d",&n); scanf("%s",s+1); for(int i=1;i<=n;i++){ if(s[i]>='A' && s[i]<='Z') a[i]=s[i]-'A'+1; else a[i]=s[i]-'a'+27; if(f[a[i]]==0) { f[a[i]]=1; m++; } //cout<<a[i]<<' '; } } int main(){ freopen("c.in","r",stdin); freopen("c.out","w",stdout); init(); printf("%d",work()); return 0; }