单调栈、队列:
如果后来的位置更优,则对队列进行更新。
两种数据结构比较相似。
单调队列
void solve()
{
cin >> n;
rep(i,1,n) cin >> a[i];
int tt = -1;
rep(i,1,n) {
while(tt != -1 && a[i] <= a[q[tt]]) tt--;
if(tt == -1) cout << "-1 ";
else cout << a[q[tt]] << " ";
q[++tt] = i;
}
}
滑动窗口
// Problem: 滑动窗口
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/156/
void solve() {
int l = 0, r = -1;
for(int i = 1; i <= n; i++) {
while(l <= r && q[l] <= i - m) l++;
while(l <= r && a[i] <= a[q[r]]) r--;
q[++r] = i;
if(i >= m) cout << a[q[l]] << " "; // 如果窗口大小固定,需要判断输出条件
}
cout << endl;
l = 1, r = 1;
p[1] = 0;
for(int i = 1; i <= n; i++) {
while(l <= r && p[l] <= i - m) l++;
while(l <= r && a[i] >= a[p[r]]) r--;
p[++r] = i;
if(i >= m) cout << a[p[l]] << " ";
}
}
Raksasa的轻功
如果严格下降,则加入队列;否则清空队列再加入。
// Problem: Raksasa的轻功
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/32275/K
void solve()
{
int ans = 0;
cin >> n;
rep(i,1,n) cin >> a[i];
int l = 1, r = 1;
q[1] = 0;
rep(i,1,n) {
if(a[i] < a[q[r]]) {
q[++r] = i;
ans = max(ans, q[r] - q[l]);
}
else {
while(l <= r) r--;
q[++r] = i;
}
}
l = 1, r = 1;
p[1] = 0;
fep(i,1,n) {
if(a[i] < a[p[r]]) {
p[++r] = i;
ans = max(ans, p[l] - p[r]);
}
else {
while(l <= r) r--;
p[++r] = i;
}
}
cout << ans;
}
理想的正方形
横着压、竖着压 https://www.cnblogs.com/wzx-RS-STHN/p/13419103.html
滑动窗口可以在
O
(
n
)
O(n)
O(n)时间内判断每个窗口的最大/最小值
窗口固定,需要判断输出的条件
void solve()
{
int ans = INT_MAX;
cin >> a >> b >> n;
rep(i,1,a)
rep(j,1,b)
cin >> res[i][j];
// max
rep(i,1,a) {
int l = 0, r = -1;
int cnt = 0;
rep(j,1,b) {
while(l <= r && q[l] <= j - n) l++;
while(l <= r && res[i][j] >= res[i][q[r]]) r--;
q[++r] = j;
if(j>=n) ma1[i][++cnt] = res[i][q[l]];
}
}
rep(j,1,b-n+1) {
int l = 0, r = -1;
int cnt = 0;
rep(i,1,a) {
while(l <= r && q[l] <= i - n) l++;
while(l <= r && ma1[i][j] >= ma1[q[r]][j]) r--;
q[++r] = i;
if(i>=n) ma2[++cnt][j] = ma1[q[l]][j];
}
}
// min
rep(i,1,a) {
int l = 0, r = -1;
int cnt = 0;
rep(j,1,b) {
while(l <= r && q[l] <= j - n) l++;
while(l <= r && res[i][j] <= res[i][q[r]]) r--;
q[++r] = j;
if(j>=n) mi1[i][++cnt] = res[i][q[l]];
}
}
rep(j,1,b-n+1) {
int l = 0, r = -1;
int cnt = 0;
rep(i,1,a) {
while(l <= r && q[l] <= i - n) l++;
while(l <= r && mi1[i][j] <= mi1[q[r]][j]) r--;
q[++r] = i;
if(i>=n)mi2[++cnt][j] = mi1[q[l]][j];
}
}
// put
rep(i,1,a-n+1) {
rep(j,1,b-n+1) {
ans = min(ans, ma2[i][j] - mi2[i][j]);
}
}
cout << ans;
}