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

来源:互联网 发布:4d设计软件 编辑:程序博客网 时间:2024/05/12 09:33

一.POJ 3061

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


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);}

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);}