双端队列和单调队列

优先队列

给定一个 $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;
}
posted @ 2025-07-09 20:06  dingchenjun  阅读(9)  评论(1)    收藏  举报