四日总结PART3

Day3-尺取,差分,前缀和

前缀和!!!这个是我开营以来遇到过的最简单的知识点。非常好用!!!

思想主要就是统计从起点到第i个点的数值总量。

直~接~上~代~码~

#include <bits/stdc++.h>
using namespace std;
long long sum[100010];
int n,m;
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        sum[i]=sum[i-1]+x;
    }
    for(int i=1;n;i++)
    {
    cout<<sum[i]<<” “;
    }
    return 0;
}

差分,主要用于解决某个区间序列的加和问题,其思想就是前缀和的逆运算。

代码如下:


#include <bits/stdc++.h>
using namespace std;
int cf[500010];
int n;
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>cf[i];
    }
    for(int i=1;i<=n;i++)
    {
    cf[i]=cf[i-1]+cf[i];
    cout<<cf[i]<<" ";
    }
    return 0;
}

双指针(或叫尺取法),是一种优化算法,就是搞两个变量代替二重循环,但其实一个变量变了,另一个也会发生变化,所以时间复杂度就是O(n);

这个最好用一道提来讲:

Problem ID: 8091

时间:1s 空间:256M

题目描述:

给定一个含有 n 个整数的数组和一个整数 s ,找出该数组中满足其和 ≥s 的长度最小的连续子数组。

如果不存在符合条件的连续子数组,输出 0。

输入格式:

第一行包含一个整数 T,表示测试数据组数。

对于每组测试数据,

第一行包含两个整数 n, s。

接下来包含 n 个整数 ai

输出格式:

对于每组测试数据,输出一个整数表示答案。

样例1

3

8 7

2 3 1 2 0 4 3 0

8 100

2 3 1 2 0 4 3 0

3 0

1 1 1

样例输出

2

0

1


#include <bits/stdc++.h>
using namespace std;
int main()
{
    int q;
    cin>>q;
    while(q--)
    {
    int f[300010];
    int minn=1e9;
   long long sum=0;
    long long n,s;
    cin>>n>>s;
    for(int i=1;i<=n;i++)
    {
        cin>>f[i];
    }
    for(int i=1,j=0;i<=n;i++)//双指针i,j
    {
       while(sum<s && j<=n)//如果总数没有到s就一直向右找
       {
             j++;
            sum+=f[j];
        }
        if(sum>=s)//如果成立
        {
            minn=min(j-i+1,minn);//比较谁小
        }
        sum-=f[i];
        }
        if(s==0) cout<<"1"<<endl;//特判
        else cout<<(minn==1e9?0:minn)<<endl;//三目运算符应该都懂吧
    }
    return 0;
}

6 个赞