尺取法

尺取法

poj 3061
下图取自网上博客
尺取法_第1张图片

#include 

int main(){
int t;
int N;
long long S,sum;
int arr[100010],i,left,right,minlen;
scanf("%d",&t);
while(t--){
    scanf("%d %I64d",&N,&S);
    for(i=0;i<N;i++)
        scanf("%d",&arr[i]);
    sum=0;left=right=0;minlen=N+1;
    do{
        if(sum>=S) {sum-=arr[left++];}
        while(sum<S&&right<N){sum+=arr[right++];}
        if(sum>=S&&minlen>right-left) minlen=right-left;
    }while(sum>=S);
    if(minlen>N)
    printf("0\n");
    else printf("%d\n",minlen);
}

}

左端一直移动,右端在值小于时向右移动,意义在于减少不必要的枚举

在连续区间上,不断调整左右两端来求解。

poj3320

#include 
#include 
#include 
#include 
#include 
using namespace std;
int arr[1000005];
int main(){
int P,i;
while(scanf("%d",&P)!=EOF){
set<int> s;
map<int,int> book;
for(i=0;i<P;i++){
    scanf("%d",&arr[i]);
    s.insert(arr[i]);}
int allpoint=s.size();
int left=0,right=0,point=0,ans=P;
do{
    if(point==allpoint){book[arr[left]]--;
    if(book[arr[left++]]==0) point--;}
    while(point<allpoint&&right<P){
       if(book[arr[right]]==0) point++;
       book[arr[right++]]++;
    }
    if(point==allpoint&&ans>right-left){ans=right-left;}
}while(point==allpoint);
printf("%d\n",ans);
}
}


问题 D: 彩色宝石项链

题目

#include 
#include 
typedef long long ll;
int main(){
char S[100005];
int gem[26];
while(scanf("%s",S)!=EOF){
    memset(gem,0,sizeof(gem));
    ll right,left,minlen,length;
    right=left=0;
    length=strlen(S);minlen=length+1;
    do{
        if(gem[0]&&gem[1]&&gem[2]&&gem[3]&&gem[4]) {gem[S[left%length]-'A']--;left++;}
        while(!(gem[0]&&gem[1]&&gem[2]&&gem[3]&&gem[4])&&right<length*2){
            gem[S[right%length]-'A']++;
            right++;
        }
        if(gem[0]&&gem[1]&&gem[2]&&gem[3]&&gem[4]&&minlen>right-left) minlen=right-left;
    }while(gem[0]&&gem[1]&&gem[2]&&gem[3]&&gem[4]);
    if(minlen>length) printf("0\n");
    else printf("%d\n",length-minlen);
}
return 0;
}

问题 E: 彩色气球

添加链接描述

题目描述

PIPI喜欢收集气球,气球有多种颜色,一共有N个气球摆成一排,第 i 个气球颜色为 Ci ,它们的位置都是固定的。PIPI喜欢五彩缤纷的气球,所以他不希望有重复的颜色。他有一次机会,可以收集任意一段连续区间内的气球。求出PIPI最多能收集多少个气球。

输入

第一行一个正整数 N ,表示共有 N 个气球。
第二行共有 N 个正整数,第 i 个正整数表示第 i 个气球的颜色 Ci
1<=N<=1e6,0<=Ci<=1e9

输出

一个整数表示PIPI最多能收集多少个气球。

样例输入

5
1 2 2 3 4

样例输出

3

#include
#include 
using namespace std;
    int N,i;
    int ballon[1000010];
  map<int,int> mp;
int main(){
while(scanf("%d",&N)!=EOF){
        mp.clear();
    for(i=0;i<N;i++)
        {scanf("%d",&ballon[i]);
        }
    int left,right,maxballon=0;
    left=right=0;
    while(true){
        while(mp[ballon[right]]==0&&right<N)  mp[ballon[right++]]=1;
        maxballon=maxballon>right-left?maxballon:right-left;
        mp[ballon[left++]]=0;
        if(right>=N) break;
    }
    printf("%d\n",maxballon);
}
return 0;
}

PIPI的开关

#include
using namespace std;
const int N=1e7+5;
int sum1[N];
char s[N];
int main(){
int n,i;
while(scanf("%d",&n)!=EOF){
        scanf("%s",s);
    if(s[0]=='1') sum1[0]=1;else sum1[0]=0;
    for(i=1;i<n;i++)
       sum1[i]=sum1[i-1]+s[i]-'0';
    int ans=sum1[n-1],l,r;
    for(l=0,r=0;r<n;r++){
        if(2*(sum1[r]-sum1[l-1])>=r-l+1) l=r+1; ///如果此区间中1的个数大于等于0的个数,左指针等于r+1
		else ans=max(ans,sum1[n-1]+r-l+1-2*sum1[r]+2*sum1[l-1]);
    }
    printf("%d\n",ans);
}
return 0;
}

你可能感兴趣的:(尺取法)