双端队列和单调队列
优先队列
给定一个 $R×C$ 的网格,每个单元格包含一个整数,找到这个网格中只包含一个不同整数的子矩形的数量;这意味着子矩形中的每个单元格都包含相同的整数。
子矩形由两个单元格定义:左上角单元格$ (r1, c1) $和右下角单元格$ (r2, c2) $,假设行从上到下编号,列从左到右编号。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=4000;
long long n,m,a[MAXN][MAXN],f[MAXN][MAXN],ans;
struct dd{
long long l,h;
};
stack<dd> s;
void F(int x){
s.push({1,f[x][1]});
for(int i=2;i<=m;i++){
if (a[x][i]!=a[x][i-1]) {
long long w=0;
while(!s.empty()){
w+=s.top().l;
ans+=s.top().h*w*(w+1)/2-(w-s.top().l)*(w-s.top().l+1)/2*s.top().h;
s.pop();
}
s.push({1,f[x][i]});
} else {
long long w=0;
while(!s.empty() && f[x][i]<s.top().h){
w+=s.top().l;
ans+=s.top().h*w*(w+1)/2-(w-s.top().l)*(w-s.top().l+1)/2*s.top().h;
s.pop();
}
ans-=w*(w+1)/2*f[x][i];
s.push({w+1,f[x][i]});
}
}
long long w=0;
while(!s.empty()){
w+=s.top().l;
ans+=s.top().h*w*(w+1)/2-(w-s.top().l)*(w-s.top().l+1)/2*s.top().h;
s.pop();
}
}
void solve(){
cin>> n >> m;
for(int i=1; i<=n;i++){
for(int j=1; j<=m;j++){
cin >> a[i][j];
if (a[i][j]==a[i-1][j]) {
f[i][j]=f[i-1][j]+1;
} else {
f[i][j]=1;
}
}
}
for(int i=1;i<=n;i++) {
F(i);
}
cout << ans << "\n";
ans=0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T;
cin >> T;
while (T--) {
solve();
}
return 0;
}
滑动窗口
滑动窗口算法是一种在序列数据(如数组、字符串等)上执行特定操作的算法。它通过在序列上滑动一个固定大小的窗口来处理数据。这个窗口可以包含序列的一部分元素,并且随着算法的执行,窗口会沿着序列移动,主要用来减少while循环。滑动窗口算法的效率通常取决于窗口大小和序列长度。在最坏情况下,滑动窗口算法的时间复杂度为O(n),其中n是序列的长度。
#include <iostream>
#include <deque>
using namespace std;
const int N = 1e6 + 10;
int arr[N];
int main() {
int n, k;
cin >> n >> k;
for (int i = 0; i < n; ++i) cin >> arr[i];
deque<int> q, index;
// 最小值部分
for (int i = 0; i < n; ++i) {
while (!q.empty() && q.back() >= arr[i]) {
q.pop_back();
index.pop_back();
}
q.push_back(arr[i]);
index.push_back(i);
if (i >= k && i - k == index.front()) {
q.pop_front();
index.pop_front();
}
if (i > k - 2) cout << q.front() << " ";
}
cout << endl;
q.clear();
index.clear();
// 最大值部分
for (int i = 0; i < n; ++i) {
while (!q.empty() && q.back() <= arr[i]) {
q.pop_back();
index.pop_back();
}
q.push_back(arr[i]);
index.push_back(i);
if (i >= k && i - k == index.front()) {
q.pop_front();
index.pop_front();
}
if (i > k - 2) cout << q.front() << " ";
}
return 0;
}
浙公网安备 33010602011771号