1 双指针
1)统计子矩阵
指针要求单调性,第一题都是头指针,第二题是头尾指针,确定用哪个,要看怎样能保持单调性。我们不希望指针调头
https://www.luogu.com.cn/problem/P8783
2)整数小拼接
https://www.luogu.com.cn/problem/P8708
点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
typedef long long ll;
ll a[N];
string s[N], str;//s[i]表示转为字符串的 a[i];str表示转为字符串的 k
ll n, k;
int cmp(string s1, string s2) {//字符串大小比较,不解释
if (s1.size() == s2.size()) {
if (s1 == s2) return 0;
else if (s1 < s2) return 1;
else return -1;
}
if (s1.size() < s2.size()) return 1;
else return -1;
}
void init() {//初始化,不解释
cin >> n >> k;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i ++ ) s[i] = to_string(a[i]);
str = to_string(k);
}
int main() {
init();
ll res = 0;
//第一遍双指针
int l = 1, r = n;
while(l <= r) {
int t = cmp(s[l] + s[r], str);
//l放前面,r放后面
if(t == 1) {//拼接后小于k
res += r - l;
l ++;
} else if(t == 0) {//拼接后等于k
res += r - l;
l ++, r --;
} else r --;//拼接后大于k
}
//第二遍双指针
l = 1, r = n;
while(l <= r) {
int t = cmp(s[r] + s[l], str);//r放前面l放后面
if(t == 1) {//同第一遍
res += r - l;
l ++;
} else if(t == 0) {
res += r - l;
l ++, r --;
} else r --;
}
cout << res;
return 0;
}
2 滑动窗口/单调队列/单调栈
日志统计
https://www.luogu.com.cn/problem/P8661
普通做法
#include<bits/stdc++.h>
using namespace std;
struct o{
int a,b;
}a[100005];
int n,d,k;
int cmp(o x,o y){
if(x.b!=y.b)return x.b<y.b;
return x.a<y.a;
}
int f1(int x, int y) {
int r = x; // 初始右端点为 x
for (int i = x; i <= y; i++) { // 遍历每个左端点 i
// 扩展右端点 r 到最远位置,使得 a[r+1].a - a[i].a < d
while (a[r + 1].a - a[i].a < d && r < y) {
r++;
}
// 窗口 [i, r] 的长度 ≥ k 则满足条件
if (r - i + 1 >= k) return 1;
}
return 0; // 所有左端点都不满足条件
}
int main()
{
cin>>n>>d>>k;
for(int i=1;i<=n;i++){
cin>>a[i].a>>a[i].b;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++){
int r=i;
while(a[r+1].b==a[i].b)r++;//找到最后一个id相同的位置
if(f1(i,r)){//判断i到r可不可以是热帖
cout<<a[i].b<<endl;
}
i=r;
}
return 0;
}
浙公网安备 33010602011771号