算法第一课
枚举
什么是枚举
一一列举
要点:不重复,不遗漏
差分与前缀和
差分和前缀和是一对对称的操作(即对差分数组求前缀和就是原数组,对前缀和求差分也会得到原数组)
离散化
例题:校门外的树
思路:
如果数据较大的话,可以使用离散化,按照每个区间的左端点排序,r 表示当前区间覆盖到的最大位置,如果subway[i].x>r,说明两个区间之间有空隙,ans+=subway[i].x-1-r,每次更新r=max(r,subway[i].y)
#include <bits/stdc++.h> using namespace std; struct subway { int x,y; }a[111]; int cmp(subway a,subway b) { return a.x<b.x; } int main() { int l,m; cin>>l>>m; for(int i=0;i<m;i++) { cin>>a[i].x>>a[i].y; } sort(a,a+m,cmp); int ans=a[0].x; int r=a[0].y; for(int i=1;i<m;i++) { if(a[i].x>r) ans+=a[i].x-1-r; r=max(r,a[i].y); } if(r<l) ans+=l-r; cout<<ans; }
尺取法/追逐法/Two-pointer(双指针)
尺取法的步骤
尺取法的整个过程分为4部:
1.初始化左右端点
2.不断扩大右端点,直到满足条件
3.如果第二步中无法满足条件,则终止,否则更新结果
4.将左端点扩大1,然后回到第二步
例题:Subsequence
#include <bits/stdc++.h> using namespace std; long long arr[100007]; long long sum[100007]; int minn; int main() { int t; cin>>t; while(t--) { memset(sum,0,sizeof(sum)); minn=0; int n,s; cin>>n>>s; for(int i=0;i<n;i++) { scanf("%d",&arr[i]); } sum[0]=arr[0]; for(int i=1;i<n;i++) { sum[i]+=arr[i]+sum[i-1]; } //printf("%d\n",sum[n-1]); if(sum[n-1]<s) { printf("0\n"); continue; } for(int r=0,l=0;r<n;r++) { if(sum[r]>=s&&minn==0) { minn=r+1; l++; } while(sum[r]-sum[l-1]>=s) { minn=min(r-(l-1),minn); l++; } } printf("%d\n",minn); } }