您的位置:首页 > 编程语言 > C语言/C++

#尺取法 --由codeforces 701C They are EveryWhere为例

2016-07-27 15:17 351 查看
尺取法
首先,尺取法就是形如一把尺子的方法,去一块一块的截取你所需要的序列。

接下来将由一个经典的尺取法例子和codeforces上的一道题对尺取法进行分析。
由简单起见,从经典的例子开始分析:

1.经典的例子  
给定一个长度为n的数列a1,a2……an及整数S,求不小于S的连续子序列的和的最小值。若解肯定存在。

input
n=10,S=15
a={5,1,3,5,10,7,4,9,2,8}


尺取法示意图:
首先,取得满足条件的最小序列,然后依次将i向右移动,若i向左移动的过程中序列仍然满足条件,则j不移动,否则将j也向右移动。在移动的过程中记录j-i的最小值。




<span style="font-size:18px;">#include<cstdio>
#include <cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

int n;
int a[200000];
int main()
{
int n,max,sum;
cin>>n>>max;
for(int k = 0 ; k < n ; k++)
cin>>a[k];
int i = 0,j = 0,sum = 0,ans = n+1;
while(1)
{
while(j < n && sum < max)//sum<max时不断循环,使得取得满足条件的序列
sum += a[j++];
if(sum < max)	break;   //若j>=n且sum小于max则输出
ans = min(j-i,ans);     //记录最小的尺度
sum -= a[i++];          //i向右移动
}
cout << ans << endl;
return 0;
}</span>


2.codeforces /701C

C. They Are Everywhere
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Sergei B., the young coach of Pokemons, has found the big house which consists of n flats ordered in a row from left to right. It is possible to enter each flat from the street. It is possible to go out from each flat. Also, each flat is connected with the
flat to the left and the flat to the right. Flat number 1 is only connected with the flat number 2 and the flat number n is only connected with the flat number n - 1.

There is exactly one Pokemon of some type in each of these flats. Sergei B. asked residents of the house to let him enter their flats in order to catch Pokemons. After consulting the residents of the house decided to let Sergei B. enter one flat from the street,
visit several flats and then go out from some flat. But they won't let him visit the same flat more than once.

Sergei B. was very pleased, and now he wants to visit as few flats as possible in order to collect Pokemons of all types that appear in this house. Your task is to help him and determine this minimum number of flats he has to visit.

Input

The first line contains the integer n (1 ≤ n ≤ 100 000) — the number of flats in the house.

The second line contains the row s with the length n, it consists of uppercase and lowercase letters of English alphabet, the i-th letter equals the type of Pokemon, which is in the flat number i.

Output

Print the minimum number of flats which Sergei B. should visit in order to catch Pokemons of all types which there are in the house.

Examples

input

3

AaA

output

2

input

7

bcAAcbc

output

3

input

6

aaBCCe

output

5

题意大致:输入n长度的字母序列,求出包含所有种类字母的最小序列。和上一题截图思路一致。

思路: 1.首先记录字母序列的包含所有种类个数
            2.用尺取法从左开始取得包含满足所有种类字母的序列,记录序列长度
            3.一次将i向右移动(下列的代码中的i用end代替)若i移动的过程中序列仍然满足包含所有种类的长度,则记录序列长度;否则将j向右移动直到序列满足包含所有种类(下列的代码中j用first代替)。

代码如下:
#include<cstdio>
#include <cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include <map>
#include <queue>
using namespace std;
const int N = 100001;
# define PI 3.141592657
const int M=2e5+7;
const int inf=1e9;
int main()
{
int n;
while (cin >> n)
{
char a
;
int letter[52];
int type = 0;

cin >> a;

memset(letter, 0, sizeof(letter));
for (int i = 0; i < n; i++)
{

if(letter[a[i]-'A']==0&&a[i]<'a')
{
letter[a[i]-'A'] = 1;
type++;
}else if(letter[a[i]-'G']==0&& a[i]>='a'){
letter[a[i]-'G'] = 1;
type++;
}
}

int first = 0,end = 0, species = 0;
int letterflag[52];
int ans = n+1;
memset(letterflag,0,sizeof(letterflag));
while (1)
{
while (first < n && species < type)
{
if( a[first]<'a'){
if(letterflag[a[first]-'A']==0 ){ species++; }
letterflag[a[first]-'A' ]++;
first ++;
}else{
if(letterflag[a[first]-'G']==0 ){ species++; }
letterflag[a[first]-'G' ]++;
first ++;
}
}
if(species<type)break;
ans = min(ans, first - end);
if (a[end]<'a')
{
if (--letterflag[a[end]-'A'] ==0)
{
species --;
}
}else{
if (--letterflag[a[end]-'G'] ==0)
{
species --;
}
}
end++;

}
cout << ans ;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息