ACM常用解题方法:尺取法

尺取法:

1.适用范围:顾名思义,像一把尺子一样量取目标,根据名字,能得到题目的一般适用范围为:连续,如果非连续估计就没什么用了。

2.好处:这样的方法能够减少大量冗余的枚举,极大优化时间,化腐朽(tle)为神奇(ac)。

3.方法:用一对下标保存左右端点,按题意移动左右端点即可。

下面是配套习题:

牛客网 Wannafly挑战赛23 A题 字符串

#include<bits/stdc++.h>

using namespace std;
map<char,int>vis;
string a;
int main()
{
    cin>>a;
    int sum=0;
    int mlen=110;
    int l=0;
    for(int i=0;i<a.length();i++)
    {
        if(!vis[a[i]]){vis[a[i]]++;sum++;}
        else vis[a[i]]++;
        //cout<<sum<<endl;
        while(sum==26)
        {
            int len=i-l+1;
            if(mlen>len)mlen=len;
            if(vis[a[l]]>1){vis[a[l]]--;l++;}
            else {break;}
        }
    }
    cout<<mlen<<endl;
    return 0;
}

poj 3061 Subsequence

#include<bits/stdc++.h>

using namespace std;
map<char,int>vis;
int a[100005];
int main()
{
    int t,n,sum=0,k,len;
    cin>>t;
    while(t--)
    {
        sum=0;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        int mlen=110000;
        for(int l=1,r=1;r<=n;r++)
        {
            sum+=a[r];
            if(sum>=k)
            {
                while(sum>=k)
                {
                    len=r-l+1;
                    mlen=min(len,mlen);
                    sum-=a[l];
                    l++;
                }
            }
        }
        printf("%d\n",mlen);
    }
    return 0;
}

poj 2739 Sum of Consecutive Prime Numbers

#include <bits/stdc++.h>
using namespace std;
const int N=1e4;
bool flag[N+10];
int prime[N+10];
int a[N];
int main()
{
    memset(flag,1,sizeof(flag));//假设全是素数
    flag[0]=0;flag[1]=0;//0和1不是素数
    int index=0;
    for(int i=2;i<=N;i++)
    {
        if(flag[i])prime[index++]=i;//得到素数集合
        for(int j=0;j<index&&prime[j]*i<=N;j++)
        {
            flag[prime[j]*i]=0;//筛合数
            if(i%prime[j]==0)break;//只筛合数的素因子最小的那一个
        }
    }
    int n;
    for(int i=2;i<=N;i++)
    {
        int sum=0;
        int cnt=0;
        int index=0;
        for(int j=0;prime[j]<=i;j++)
        {
            sum+=prime[j];

            if(sum<i)continue;
            while(sum>i)
            {
                sum-=prime[index];
                index++;
            }
            if(sum==i)cnt++;
        }
        a[i]=cnt;
    }
    while(~scanf("%d",&n)&&n)
    {
        printf("%d\n",a[n]);
    }
    return 0;
}

poj 2100 Graveyard Design

我英语是真的菜,还以为是设计什么花园,结果是墓地。。
这题数据一开始用我用int,结果疯狂tle,我就震惊了,刚学的尺取法都tle了,那我还做个屁,没想到看解题报告,是数据问题,以前爆int都是wa,这次居然是tle,长见识了。。

#include <bits/stdc++.h>
using namespace std;
int a[1020][3];
typedef long long ll;
struct node
{
    ll l,ri,c;
}p[1020];
int main()
{
    long long s;
    scanf("%lld",&s);
    long long sum=0;
    ll index=1;
    ll cnt=0;

    for(long long i=1;i*i<=s;i++)
    {
        sum+=i*i;
        if(sum<s)continue;
        while(sum>s)//忘记这里是while了,检查了几遍
        {
            sum-=index*index;
            index++;
        }
        if(sum==s)
        {
            p[cnt].c=i-index+1;
            p[cnt].l=index;p[cnt].ri=i;
            cnt++;
        }
    }
    printf("%lld\n",cnt);
    for(ll i=0;i<cnt;i++){
        printf("%lld ",p[i].c);
        for(ll k=p[i].l;k<=p[i].ri;k++)
        printf("%lld ",k);

    printf("\n");
    }
    return 0;
}

poj 3320 Jessica’s Reading Problem

这题被林大oj一顿爆坑,tle三回,我想这TM不可能爆int啊,就找了poj原题提交,结果516ms。。

#include <bits/stdc++.h>
using namespace std;
map<int,int>vis1,vis2;
int a[1000005];
int main()
{
    int n;
    scanf("%d",&n);
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(!vis1[a[i]])sum++;
        vis1[a[i]]++;
    }
    int l=1,cnt=0;
    int mlen=1000000;
    int len;
    for(int r=1;r<=n;r++)
    {
        if(!vis2[a[r]])cnt++;
        vis2[a[r]]++;
        while(cnt==sum&&l<=r)
        {
            len=r-l+1;
            mlen=min(mlen,len);
            if(vis2[a[l]]>1){vis2[a[l]]--;l++;}
            else break;
        }
    }
    printf("%d\n",mlen);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhoucheng_123/article/details/104623165