Take ruler France

Take gauge method (also known as:? Range peristalsis) applies in the sequence required to meet the continuous (shortest) Interval certain conditions, the number of columns must meet certain monotony: the most common is that the left does not satisfy the condition tends to point to the right, right tend to point to the right to meet the conditions.

POJ3061
shortest section and the section to meet the greater than equal to k.
First, the sequence number is positive, and if it is greater than a range of equal to S, then no back right propulsion point, and since it is certainly not less than S but greater length, so that, when the right end of the interval and less than S point moves to the right, and greater than equal to S, the left point to the right to find the shortest interval further, if the right point to the end of the section which is not greater than and equal to S, the end section of the enumeration.

//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int a[100010];
int main(){
    int T;    cin>>T;
    while(T--){
        int n,st=1,en=0,k;  cin>>n>>k;
        for(int i=1;i<=n;++i) cin>>a[i];
        int sum=0,ans=100010;
        while(1){
            while(en<n&&sum<k) {
                ++en;sum+=a[en];
            }
            if(sum<k) break;
            ans=min(ans,en-st+1);
            sum-=a[st];++st;
        }
        if(ans==100010) cout<<"0"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}


POJ3320
a book has P pages, each page a knowledge point, at least to seek consecutive pages cover all the knowledge points.

#include<iostream>
#include<map>
#include<stdio.h>
using namespace std;
map<int,int> vis;
int num[1000010];
int main(){
    int n,cnt=0;
    scanf("%d",&n);
    for(int i=1;i<=n;++i) {
        scanf("%d",&num[i]);
        if(vis[num[i]]==0) {
            ++cnt;vis[num[i]]=1;
        }
    }
    for(int i=1;i<=n;++i){
        vis[num[i]]=0;
    }
    int res=0,st=1,en=0,ans=1000010;
    if(cnt==0){
        cout<<"0";return 0;
    }
    while(1){
        while(en<n&&res<cnt){
            ++en;
            if(vis[num[en]]==0) {++res;}
            ++vis[num[en]];
        }
        if(res<cnt) break;
        ans=min(ans,en-st+1);
        --vis[num[st]];
        if(vis[num[st]]==0) --res;
        ++st;
    }
    printf("%d",ans);
    return 0;
}

LGP1381 recite the word
given n words, to find the shortest continuous portion of the list containing the m words comprising as many words the n
first hash, and then take foot (and similar to the previous question)

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const ULL p=1e6+3;
const ULL mod=1e9+7;
char str[1010][20];
char str2[100010][20];
ULL Hash(char* s){
    int len=strlen(s);
    ULL tmp=0;
    for(int i=0;i<len;++i){
        tmp=(tmp*p+ULL(s[i]-'a'))%mod;
    }
    return tmp;
}
ULL HASH[1010];
ULL HASH2[100010];
map<ULL,int> mmp;
map<ULL,int> cnt;
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%s",str[i]);
        HASH[i]=Hash(str[i]);
        mmp[HASH[i]]=1;
    }
    int m;
    scanf("%d",&m);
    int ans1=0;
    for(int i=1;i<=m;++i){
        scanf("%s",str2[i]);
        HASH2[i]=Hash(str2[i]);
        if(mmp[HASH2[i]]==1){
            ++ans1;
            ++mmp[HASH2[i]];
        }
    }
    int st=1,en=0,sum=0,ans2=1000010;
    if(ans1==0){
        cout<<"0\n0";
        return 0;
    }
    cnt.clear();
    while(1){
        while(en<m&&sum<ans1){
            ++en;
            if(mmp[HASH2[en]]>0&&cnt[HASH2[en]]==0) {
                ++sum;
            }
            ++cnt[HASH2[en]];
        }
        if(sum<ans1) break;
        ans2=min(ans2,en-st+1);
        --cnt[HASH2[st]];
        if(cnt[HASH2[st]]==0&&mmp[HASH2[st]]>0) --sum;
        ++st;
    }
    cout<<ans1<<endl<<ans2<<endl;;
}


poj2566
minimum and an array of a given value t, such that it is seeking a sub-interval t and the absolute value of the difference, if there are multiple, arbitrary solutions are feasible.
Obviously, the first question to borrow ideas, as we have to find a sub-interval and makes the closest t, then keep looking than the current range and greater range, and if the interval is already greater than or equal t, then do not need to go looking for greater range, because the greater the difference between it and the t's and dot the interval left to right to move to advance. Therefore, after the calculation according to the first interval and all, can be sorted according to the above idea for solving

#include<iostream>
#include<map>
#include<stdio.h>
#include<algorithm>
using namespace std;
struct ac{
    int v,pos;
}num[100010];
bool cmp(ac a1,ac a2){
    return a1.v<a2.v;
}
int main(){
    int n ,k;
    while(~scanf("%d%d",&n,&k)&&(n!=0&&k!=0)){
        num[0].v=0;num[0].pos=0;int x;
        for(int i=1;i<=n;++i){
            scanf("%d",&x);
            num[i].pos=i;num[i].v=x+num[i-1].v;
        }
        sort(num,num+1+n,cmp);
        int t;
        while(k--){
            int st=0,en=1;
            scanf("%d",&t);
            int SUB=2000000010,ans,ansl,ansr;
            while(st<=n&&en<=n){
                int pre=abs(num[en].v-num[st].v);
                int q=abs(t-pre);
                if(q<SUB){
                    SUB=q;
                    ans=pre;
                    ansl=num[st].pos;ansr=num[en].pos;
                }
                if(pre>t) ++st;
                else if(pre<t) ++en;
                else break;
                if(st==en) ++en;
            }
            if(ansl>ansr) swap(ansl,ansr);
            printf("%d %d %d\n",ans,ansl+1,ansr);
        }
    }
    return 0;
}


POJ2739
find a number, it can be and how many consecutive prime numbers (and similar to the first question, but the requirements are not the same thing)

//#include<bits/stdc++.h>
#include<iostream>
#include<stdio.h>
using namespace std;
int prim[100000];
int flag[100000];
void List(){
    int cnt=0;
    for(int i=2;i<100000;++i){
        if(flag[i]==0) {
            prim[++cnt]=i;
        }
        for(int j=1;j<=cnt;++j){
            if(prim[j]*i>=100000) break;
            flag[prim[j]*i]=1;
            if(i%prim[j]==0) break;
        }
    }
}
int main(){
    List();
    int x;
    while(scanf("%d",&x)!=EOF&&x){
        int st=1,en=0,sum=0,ans=0;
        while(1){
            while(en<100000&&sum<x){
                ++en;
                sum+=prim[en];
            }
            if(sum==x)  ++ans;
            if(prim[en]>x) break;
            sum-=prim[st];
            ++st;
        }
        cout<<ans<<endl;
    }
    return 0;
}

POJ2100
find a number can be (a question as it appeared on) how many squares of integers and

#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
pair<long long,pair<long long,long long> > ans[1000];
int main(){
    long long n;
    long long sum2=0;
    scanf("%lld",&n);
    long long sum=0,st=1,en=0;
    int cnt=0;
    while(1){
        while(sum<n){
            ++en;
            sum+=en*en;
        }
        if(sum==n) {
            ans[++cnt]=make_pair(en-st+1,make_pair(st,en));
        }
        if(en*en>n) break;
        sum-=st*st;++st;
    }
    printf("%d\n",cnt);
    for(int i=1;i<=cnt;++i){
        printf("%lld ",ans[i].first);
        for(int j=ans[i].second.first;j<=ans[i].second.second;++j){
            printf("%lld ",j);
        }
        printf("\n");
    }
    return 0;
}

Published 96 original articles · won praise 11 · views 2275

Guess you like

Origin blog.csdn.net/weixin_43769146/article/details/103486791