单调队列的定义
单调队列是一种特殊的队列数据结构,其元素保持严格的单调递增或单调递减顺序。与普通队列不同,单调队列在插入新元素时会移除破坏单调性的旧元素,确保队列始终有序。
核心特性
单调性维护:队列内的元素按单调递增或单调递减排列。
动态调整:插入新元素时,需从队列尾部或头部移除不符合单调性的元素。
高效操作:支持在均摊 (O(1)) 时间复杂度内完成插入、删除和查询操作。
典型应用场景
滑动窗口最大值/最小值:luogu P1886,通过单调队列在 (O(n)) 时间内解决。
优化动态规划:减少状态转移的时间复杂度,例如多重背包问题。
模板外简单题就直接放代码了 \color{red} {模板外简单题就直接放代码了} 模板外简单题就直接放代码了
滑动窗口
我们需要维护一个队列,这个队列是具有单调性的。
维护这个队列每加入一个元素有三步:
如果是单调递减队列:
排出所有比目前元素更的大的。
然后加入该元素。
排出所有过时元素。
如果是单调递增队列:
排出所有比目前元素更的小的。
然后加入该元素。
排出所有过时元素。
完整代码:
#include<bits/stdc++.h>
using namespace std;
int n,k,q[1000005],a[1000005];
void minn()
{
int l = 1,r = 0;
for(int i = 1;i <= n;i ++)
{
while(l <= r && a[q[r]] >= a[i] )
{
r --;
}
q[++ r] = i;
while(l <= r && q[l] <= i - k)
{
l ++;
}
if(i >= k)cout << a[q[l]] << ' ';
}
}
void maxn()
{
int l = 1,r = 0;
for(int i = 1;i <= n;i ++)
{
while(l <= r && a[q[r]] <= a[i] )
{
r --;
}
q[++ r] = i;
while(l <= r && q[l] <= i - k)
{
l ++;
}
if(i >= k)cout << a[q[l]] << ' ';
}
}
int main()
{
cin >> n >> k;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
}
minn();
cout << '\n';
maxn();
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int stk[500005],maxn[500005],minn[500005],a[500005],n,top,l = 1,r = 1,cnt;
int main()
{
cin >> n;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
}
a[n + 1] = -1;
for(int i = 1;i <= n + 1;i ++)
{
while(top > 0 && a[i] < a[stk[top]])
{
minn[stk[top]] = i;
top --;
}
stk[++ top] = i;
}
top = 0;
a[n + 1] = INT_MAX;
for(int i = 1;i <= n + 1;i ++)
{
while(top > 0 && a[i] >= a[stk[top]])
{
maxn[stk[top]] = i;
top --;
}
stk[++ top] = i;
}
while(l <= n)
{
while(maxn[r] < minn[l])
{
r = maxn[r];
}
l = r + 1;
cnt ++;
r = l;
}
cout << cnt;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int M = 2e5 + 5;
int n,stk[M],t[M],a[M],top,ans;
signed main()
{
cin >> n;
for(int i = 1;i <= n;i ++)
{
cin >> t[i];
if(i > t[i])
{
cout << -1;
return 0;
}
}
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
}
stk[++top] = a[n];
ans += a[n];
for(int i = n - 1;i >= 0;i --)
{
if(t[i] == t[i + 1])
{
if(stk[top] >= a[i])
{
int x = stk[top];
stk[++top] = x;
ans += x;
}
else
{
stk[++top] = a[i];
ans += a[i];
}
}
else
{
for(int j = 1;j <= t[i + 1] - t[i];j ++)
{
if(top > 0)
{
top --;
}
else
{
break;
}
}
if(top > 0 && stk[top] >= a[i])
{
int x = stk[top];
stk[++top] = x;
ans += x;
}
else
{
stk[++top] = a[i];
ans += a[i];
}
}
}
cout << ans;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int n,k,q[1000005];
unsigned long long a[1000005];
void maxn()
{
int l = 1,r = 0;
for(int i = 1;i <= n;i ++)
{
while(l <= r && a[i] >= a[q[r]])
{
r --;
}
q[++r] = i;
while(l <= r && q[l] <= i - k)
{
l ++;
}
if(i >= k)cout << r - l + 1 << '\n';
}
}
int main()
{
cin >> n >> k;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
}
maxn();
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int n,d,k;
int t = 1 , l , r , q[100050];
struct node
{
int ts,id;
}a[100050];
bool cmp(node x,node y)
{
if(x.id != y.id)return x.id < y.id;
return x.ts < y.ts;
}
int main()
{
cin >> n >> d >> k;
for(int i = 1 ; i <= n ; i ++)
{
cin >> a[i].ts >> a[i].id;
}
sort(a + 1 , a + n + 1 , cmp);
for(int i = 1 ; i <= n ; i ++)
{
while(a[t].id == a[i].id)i ++;
i --;
l = 1;
r = 0;
for(int j = t ; j <= i ; j ++)
{
while( l <= r && a[q[l]].ts + d <= a[j].ts ) l ++;
q[ ++ r ] = j;
if( r - l + 1 >= k )
{
cout << a[t].id << '\n' ;
t = i + 1;
break;
}
if(j == i) t = i + 1;
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
deque<int>qn;
vector<int>minn;
int n,m,a[2000005];
int main()
{
scanf("%d %d",&n,&m);
for(int i = 1;i <= n;i ++)
{
scanf("%d",&a[i]);
if(!qn.empty() && qn.front() == i - m - 1)
{
qn.pop_front();
}
while(!qn.empty() && a[qn.back()] >= a[i - 1])
{
qn.pop_back();
}
if(i != 1)qn.push_back(i - 1);
if(!qn.empty())minn.push_back(a[qn.front()]);
else minn.push_back(0);
}
for(auto it:minn)printf("%d\n",it);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int M = 3e6 + 5;
int n,k,qn[M],qx[M],a[M],ln = 1,lx = 1,rn,rx,pos = 1,ans;
int main()
{
cin >> k >> n;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
}
for(int i = 1;i <= n;i ++)
{
while(ln <= rn && a[qn[rn]] >= a[i])
{
--rn;
}
while(lx <= rx && a[qx[rx]] <= a[i])
{
--rx;
}
qn[++rn] = i;
qx[++rx] = i;
while(ln <= rn && lx <= rx && (a[qx[lx]] - a[qn[ln]]) > k)
{
if(qx[lx] < qn[ln])
{
pos = qx[lx] + 1;
lx ++;
}
else
{
pos = qn[ln] + 1;
ln ++;
}
}
ans = max(ans,i - pos + 1);
}
cout << ans;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int M = 1e5 + 5;
int t,n,k,a[M],qn[M],qx[M],ln = 1,lx = 1,mxn[M],mnn[M],ans = 2e9,rn,rx;
bool flag = false;
int check(int len)
{
int cnt = 0;
ln = 1,lx = 1,rn = 0,rx = 0;
for(int i = 1;i <= n;i ++)
{
while(ln <= rn && a[qn[rn]] >= a[i]) // Min
{
-- rn;
}
while(lx <= rx && a[qx[rx]] <= a[i]) // Max
{
-- rx;
}
qn[++ rn] = i;
qx[++ rx] = i;
while(ln <= rn && qn[ln] <= i - len)
{
++ ln;
}
while(lx <= rx && qx[lx] <= i - len)
{
++ lx;
}
if(i >= len)
{
if(!flag)
{
ans = min(a[qx[lx]] - a[qn[ln]] , ans);
}
else
{
if(a[qx[lx]] - a[qn[ln]] >= ans)
{
cnt ++;
}
}
}
}
flag = true;
return cnt;
}
int main()
{
cin >> t;
while(t --)
{
ans = 2e9;
flag = false;
cin >> n >> k;
for(int i = 1;i <= n;i ++)cin >> a[i];
check(n - k + 1);
int l = 0,r = n - k + 2;
while(l + 1 < r)
{
int mid = (l + r) / 2;
if(check(mid) >= k)
{
r = mid;
}
else
{
l = mid;
}
}
cout << ans << ' ' << r << '\n';
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
struct node
{
int pos,it;
};
deque < node > q;
int n,k,a[2000005];
int main(){
cin >> n >> k;
for(int i = 1;i <= n;i ++)cin >> a[i];
for(int i = 1;i <= n;i ++)
{
if( !q.empty() && q.front().pos <= i - k )
{
q.pop_front();
}
while( !q.empty() && q.back().it <= a[i] )
{
q.pop_back();
}
q.push_back( { i , a[i] } );
if(i >= k)cout << q.front().it << '\n';
}
return 0;
}
P3029 [USACO11NOV] Cow Lineup S
#include<bits/stdc++.h>
using namespace std;
struct node
{
int x,id;
}s[50005];
int ans = INT_MAX,sum,n,z,rx;
map<int,int>t;
map<int,bool>pan;
bool cmp(node a,node b)
{
return a.x < b.x;
}
int main() {
cin >> n;
for(int i = 1 ; i <= n ; i ++)
{
cin >> s[i].x >> s[i].id;
if(pan[ s[ i ].id ] == false)
{
sum ++;
pan[ s[ i ].id ] = true;
}
}
sort(s + 1 , s + n + 1 , cmp);
rx = 1;
t[ s[ 1 ].id ] ++;
z=1;
for(int i = 1 ; i <= n ; i ++)
{
while(z < sum && rx < n)
{
rx ++;
t[ s[ rx ].id ] ++;
if( t[ s[ rx ].id ] == 1 ) z ++;
}
if(z == sum)
{
ans = min( ans , s[rx].x - s[i].x );
}
t[ s[ i ].id ] --;
if( t[ s[ i ].id ] == 0 )
{
z --;
}
}
cout << ans;
return 0;
}
#include <bits/stdc++.h>
#define c(x) scanf("%d",&x)
#define p(x) printf("%d\n",x)
using namespace std;
const int N = 1e5 + 5;
map < int , int > g;
int n,k;
int a[N];
int main()
{
c(n);
c(k);
for(int i = 1 ; i <= n ; i ++)
{
c(a[i]);
}
int l = 1 , r = 0 , cnt = 0 , ans = 0;
while(r <= n)
{
if(++ g[ a[ ++ r ] ] == 1) cnt ++;
while(cnt == k + 2)
{
if( !( -- g[ a[ l ++ ] ] ) )
{
cnt --;
}
}
ans = max( ans , g[ a[ r ] ] );
}
p(ans);
return 0;
}
1007

被折叠的 条评论
为什么被折叠?



