acm常用技巧二 POJ 3061 POJ 3320 POJ 3276 尺取法

一.POJ 3061

给n个非负数,求出连续的m个数的和加起来比k;求最小的m

acm常用技巧二 POJ 3061 POJ 3320 POJ 3276 尺取法_第1张图片

int n,S;
int a[MXN];
int sum[MXN];

void Fun(){
    for(int i=0;i<n;++i){
        sum[i+1]=sum[i]+a[i];
    }
    if(sum[n]<S){
        puts("0");
        return;
    }
    int res=n;
    for(int s=0;sum[s]+S<=sum[n];++s){
        int t=lower_bound(sum+s,sum+n,sum[s]+S)-sum;
        res=min(res,t-s);
    }
    printf("%d\n",res);
}

acm常用技巧二 POJ 3061 POJ 3320 POJ 3276 尺取法_第2张图片

void Fun(){
    int res=n+1;
    int s=0,t=0,sum=0;
    while(1){
        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;
    printf("%d\n",res);
}


二.POJ 3320

找一段最短的子串使得它包含所有该序列中出现过的数字


int P;
int a[MXNP];
void Fun(){
    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;
    while(1){
        while(t<P&&num<n){
            if(count[a[t++]]++==0)
                num++;
        }
        if(num<n) break;
        res=min(res,t-s);
        if(--count[a[s++]]==0){
            --num;
        }
    }
    printf("%d\n",res);
}

三.POJ 3276

int N;
int dir[MXN];
int f[MXN];

int calc(int K){
    memset(f,0,sizeof(f));
    int res=0;
    int sum=0;
    for(int i=0;i+K<=N;++i){
        if((dir[i]+sum)%2){
            ++res;
            f[i]=1;
        }
        sum+=f[i];
        if(i-K+1>=0)
            sum-=f[i-K+1];
    }
    for(int i=N-K+1;i<N;++i){
        if((dir[i]+sum)%2){
            return -1;
        }
        if(i-K+1>=0)
            sum-=f[i-K+1];
    }
    return res;
}
void Fun(){
    int K=1,M=N;
    for(int k=1;k<=N;++k){
        int m=calc(k);
        if(m>=0&&M>m){
            M=m;
            K=k;
        }
    }
    printf("%d %d\n",K,M);
}




你可能感兴趣的:(ACM)