就是两个指针表示区间[l,r]的开始与结束然后根据题目来将端点移动,是一种十分有效的做法。适合连续区间的问题
具体做法是:
1.初始化左右端点
2.不断扩大右端点,直到满足条件
3.如果第二步中无法满足条件,则终止,否则更新结果
4.将左端点扩大1,然后回到第二步
几个例子:
1、Codeforces Round #364 (Div. 2) 点击打开链接
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.
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.
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.
3
AaA
2
7
bcAAcbc
3
6
aaBCCe
5
In the first test Sergei B. can begin, for example, from the flat number 1 and end in the flat number 2.
In the second test Sergei B. can begin, for example, from the flat number 4 and end in the flat number 6.
In the third test Sergei B. must begin from the flat number 2 and end in the flat number 6.
AC代码:
<span style="font-size:14px;">#include<stdio.h>
#include<string.h>
int main()
{
int n,temp=0,i,ans;char s[100010];int a[200];
memset(a,0,sizeof(a));
scanf("%d",&n);
scanf("%s",s);
for(i=0;i<n;i++)
{
a[s[i]]=1;
}
for(i=65;i<=122;i++)
if(a[i]) temp++;
memset(a,0,sizeof(a));
int l=0,r=0,now=1;ans=n+1;
a[s[l]]=1;
while(1)
{
while(r<n-1)
{
if(now==temp) break;
r++;
if(!a[s[r]]) {now++;}
a[s[r]]++;
}
if(now<temp) break;
if(r-l+1<ans) ans=r-l+1;
if((--a[s[l]])==0) now--;
l++;
}
printf("%d\n",ans);
}</span>
2、POJ 2566 点击打开链接
Time Limit: 5000MS | Memory Limit: 65536K | |||
Total Submissions: 2906 | Accepted: 892 | Special Judge |
Description
You are given the sequence of n integers and the non-negative target t. You are to find a non-empty range of the sequence (i.e. a continuous subsequence) and output its lower index l and its upper index u. The absolute value of the sum of the values of the sequence from the l-th to the u-th element (inclusive) must be at least as close to t as the absolute value of the sum of any other non-empty range.
Input
Output
Sample Input
5 1
-10 -5 0 5 10
3
10 2
-9 8 -7 6 -5 4 -3 2 -1 0
5 11
15 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
15 100
0 0
Sample Output
5 4 4
5 2 8
9 1 1
15 1 15
15 1 15
题意:有n个数,m次访问,每次访问找出一个连续的子序列使得他们的和最接近t。输出这个和,和序列的左右端点。
思路:这里用前缀和先预处理一下,并排序,然后再用尺取法
AC代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
struct node
{
long long x,y;
}b[100010];
int cmp(node a,node b)
{
return a.x<b.x;
}
int main()
{
long long n,k,t,a[100010],temp,ans,l,r,i,judge,ansl,ansr;
while(scanf("%lld%lld",&n,&k)!=EOF&&(n!=0||k!=0))
{
a[0]=0;b[0].x=0,b[0].y=0,temp=0;
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
temp+=a[i];
b[i].x=temp;
b[i].y=i;
}
sort(b,b+n+1,cmp);
while(k--)
{
l=0;r=1;judge=1<<30;long long now;ans=b[1].x;ansl=1,ansr=1;
scanf("%lld",&t);
while(r<=n&&judge)
{
now=b[r].x-b[l].x;
if(abs((int)(now-t))<judge)
{
judge=abs((int)(now-t));
ans=now;
ansl=b[l].y;
ansr=b[r].y;
}
if(now<t) r++;
if(now>t) l++;
if(r==l) r++;
}
if(ansl>ansr) swap(ansl,ansr);
printf("%lld %lld %lld\n",ans,ansl+1,ansr);
}
}
}