双指针
遍历每个区间的双指针 最后 while() i=j-1
搭档
给出一群男女的各自的魅力值 只有魅力值之差为小于等于1的时候才会搭档 求出最多可以同时多少对搭档
排序+男女指针,
先将男、女魅力值排序,如果可以搭档,那是最好。若不能,就调魅力值小的那一边向后走
sort(a + 1, a + n + 1);
sort(b + 1, b + m + 1);
while (i <= n && j <= m) {
if(abs(a[i] - b[j]) <= 1) ans ++, i ++, j ++;
else if(a[i] > b[j]) j ++;//b小 b向右走
else if(a[i] < b[j]) i ++;
}
奶牛棒球https://www.acwing.com/problem/content/description/1947/
(X,Y,Z) 需满足,Y 在 X 的右边,Z 在 Y 的右边,并且从 Y 到 Z 的距离在 [XY,2XY] 之间,其中 XY 表示从 X 到 Y 的距离。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010;
int n;
int p[N];
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i ++ ) scanf("%d", &p[i]);
sort(p, p + n);
int res = 0;
for (int i = 0; i + 2 < n; i ++ )//i+2是因为需要给后面的两个指针留下标位置
for (int j = i + 1, l = j + 1, r = j + 1; j + 1 < n; j ++ )//i+1是因为需要给后面的一个指针留位置
{// j-i < k-j < 2*(j-i ) 对于满足区域的k都可以
while (l < n && p[l] - p[j] < p[j] - p[i]) l ++ ;//左端点l++是找到最左边的满足条件所以是<
while (r < n && p[r] - p[j] <= 2 * (p[j] - p[i])) r ++ ;//右端点是找到最右边满足条件所以是>
res += r - l;//计算下标
}
printf("%d\n", res);
return 0;
}
最长重复子序列
双指针
当发现s[a[i]]>1 减少的是s[a[j]]而不是s[a[i]]
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int s[N],a[N];
int n,res;
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ ) cin >> a[i];
for (int i = 0,j=0; i < n; i ++ ){
s[a[i]]++;
while(j<n&&s[a[i]]>1){
s[a[j]]--;
j++;
}
res=max(res,i-j+1);
}
cout << res;
return 0;
}
数组元素的目标和https://www.acwing.com/video/252/
如果我的 a从小到大 b从大到小枚举 当a+b超过目标值的时候就b就变小 o m+n的复杂度
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e5+10;
int a[N],b[N];
int main()
{
int n,m,x;cin>>n>>m>>x;
for (int i = 0; i < n; i ++ ) cin >> a[i];
for (int i = 0; i < m; i ++ ) cin >> b[i];
for (int i = 0,j=m-1; i < n; i ++ ){
while(j>=0&&a[i]+b[j]>x) j--;
if(a[i]+b[j]==x){
cout << i<<" "<<j;
break;
}
}
return 0;
}
判断子序列https://www.acwing.com/problem/content/2818/
判断数组a的数 是不是数组b的 子序列
那么就i 和 j 分别从0开始 先让j移动当i
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
for (int i = 0; i < m; i ++ ) scanf("%d", &b[i]);
int i = 0, j = 0;
while (i < n && j < m)//
{
if (a[i] == b[j]) i ++ ;
j ++ ;
}
if (i == n) puts("Yes");
else puts("No");
return 0;
}
日志统计https://www.acwing.com/problem/content/1240/
int main()
{
scanf("%d%d%d", &n, &d, &k);
for (int i = 0; i < n; i ++ ) scanf("%d%d", &logs[i].x, &logs[i].y);
//x是时间点 y是id 以x为时间段
sort(logs, logs + n);
for (int i = 0, j = 0; i < n; i ++ )
{
int id = logs[i].y;
cnt[id] ++ ;
while (logs[i].x - logs[j].x >= d)
{
cnt[logs[j].y] -- ;
j ++ ;//满足条件
}
if (cnt[id] >= k) st[id] = true;
}
for (int i = 0; i <= 100000; i ++ )
if (st[i])
printf("%d\n", i);
return 0;
}
最长连续子序列https://www.acwing.com/problem/content/4397/
不超过k重复的个数
双指针
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6+10;
int w[N],cnt[N];
int main()
{
int n,k;
cin >> n>>k;
for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
int res=0,l,r;
for (int i = 1, j = 1,t = 0 ; i <= n; i ++ ){
if(cnt[w[i]]==0) t++;
cnt[w[i]]++;
while( t>k ){
if(cnt[w[j]]==1) t--;
cnt[w[j]]--;
j++;
}
if(i-j+1>res){
res=i-j+1;
l=j,r=i;
}
}
cout << l<<" "<<r;
return 0;
}
最大子矩阵
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 2005,inf=1e9;
int s1[N],s2[N];
int a[N],b[N];
int main()
{
int n,m;
cin >> n>>m;int x;
for (int i = 1; i <= n; i ++ ){
scanf("%d", &x);
s1[i]=s1[i-1]+x;
}
for (int i = 1; i <= m; i ++ ){
scanf("%d", &x);
s2[i]=s2[i-1]+x;
}
for (int len = 1; len <= n; len ++ ){//获取 这个长度的数组的最小值
a[len]=inf;
for (int i = 1; i+len-1 <= n; i ++ ){
int j=i+len-1;
a[len]=min(a[len],s1[j]-s1[i-1]);
}
}
for (int len = 1; len <= m; len ++ ){
b[len]=inf;
for (int i = 1; i+len-1 <= m; i ++ ){
int j=i+len-1;
b[len]=min(b[len],s2[j]-s2[i-1]);
}
}
int res=0;cin>>x;
for (int i=1,j=m;i<=n;i++){//最大
while(j&& a[i]>x/b[j] ) j--;
res=max(res,j*i);
}
cout << res;
return 0;
}
天气预报https://ac.nowcoder.com/acm/contest/30532/G
求满足区间里面 0的个数>a&&1的个数>b 连续的区间数个数
因为是连续的 所以左端点固定后 j到达满足的情况后 j及j后面的答案都满足 res++n-j+1;
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
long long cnt[2];
signed main(){
int n,a,b;
cin>>n>>a>>b;
string s;cin>>s;
s=" "+s;
long long res=0;
if(a==0&&b==0) {
res++;
}
for(int i=1,j=0;i<=n;i++){
int t=0;
if(s[i]=='0') t=0;
else t=1;
while(j<n&&(cnt[0]<a||cnt[1]<b) ){
j++;
cnt[s[j]-'0']++;
}
if((cnt[0]>=a&&cnt[1]>=b))
res+=n-j+1;
cnt[s[i]-'0']--;//记得删除
}
cout<<res;
return 0;
}