足は、エミュレート
(シモンズ:参考図書:課題プログラミング)
足は、エミュレート:サイズエミュレート配列は通常、ポイントを中心に選択された間隔で、答えに間隔エンドポイントに関する実際の状況に応じて前進し続ける下の標準のペアを保存されます。
私たちはしばしばスキルを使用する必要があります。(足は非常によく理解してエミュレートされました)
状況は?定規を使用してエミュレートすることができるものの下で
要求の対象とした場合、隣接サブシーケンスを見つける列の所定の数が合計よりも大きい/又は値以下で、次いで必要な最小長さです。
言い換えれば、それは連続したサブシーケンスのためにする必要があり:その名のように、定規を取る、連続期間でなければなりません。そして、前面から背面に実行されています。
特定のトピックを見てそこに持っています。
の使用に関連します
直接参考例です。
図に示すように、ステップは、足を取ら:
1。私たちに直接よりも右第1蓄積以上に左またはSに等しい、この時点では、レコードの長さから、最初のステップを開始します
2。それは以上でS、更新の長さ、反復される場合に、最も左の値を減算
または右組み合わせ、追加されたことは2を繰り返し、以上Sである
3 また、この時の最小の長さ、それの最後に更新された列を、最後に移動。。。。。。。
それが右に来るように残されているので、時間計算量はO(n)があります
コード
コードはまた、借入のテンプレート定規として見ることができます
#include<iostream>
using namespace std;
const int maxn = 10005;
int n;
int S;
int a[maxn];
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
int res =n+1; //长度
int s=0,t=0,sum=0; //s:当前最左边位置 t:当前最右边位置
// sum:是否大于等于S
for(;;){
while(t<n && sum<S){
sum += a[t++];
}
if(sum<S) break; //即是累加,也是最后出口
res = min(res,t-s);
sum -= a[s++];
}
if(res >n){ //不存在这样的子序列
res =0; //输出0
}
cout<<res<<endl;
return 0;
}
この道を見て、同じ基本的な考え方、
#include<iostream>
#include<set>
#include<map>
using namespace std;
const int maxn = 1e6+5;
int p;
int a[maxn];
int main(){
//读入
cin>>p;
for(int i=0;i<p;i++){
cin>>a[i];
}
//用set,可自动去重,排序
set<int> all;
for(int i=0;i<p;i++){
all.insert(a[i]);
}
int n=all.size();
//尺取法
int s=0,t=0,num=0;
map<int,int> count;
int res=p;
for(;;){
while(t<p && num<n){
if(count[a[t++]] ++== 0){ //如果count[a[t]]==0;那就加1;然后t++;
//一直加到num== 页数n
num++;
}
}
if(num<n) break; //一直累加到num==n,或是到最后 循环出口
res = min(res,t-s);
if(-- count[a[s++]] == 0){ //把目前最前面的一个去掉
num--;
}
}
cout<<res<<endl;
return 0;
}