数据结构往往可以在不改变主算法的前提下题高运行效率,具体做法可能千差万别,但思路却是有规律可循
经典问题:滑动窗口 单调队列O(n)
POJ 2823
我开始写的: TLE 说明STL的库还是有点慢
#include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<queue> #include<deque> #include<set> #include<map> #include<cmath> #include<stack> const double PI = acos(-1.0); #define INF 0x3f3f3f3f typedef long long ll; using namespace std; struct Deq { int idx; int w; }; deque<Deq> q; deque<Deq> qq; int Max[1000005]; int main() { int n, k; int x; int cnt = 0; scanf("%d%d", &n, &k); for (int i = 0; i < n; i++) { if (i < k) { scanf("%d", &x); Deq qqq; qqq.idx = i; qqq.w = x; if (q.empty()) q.push_back(qqq); if (qq.empty()) qq.push_back(qqq); else { while (!q.empty() && q.back().w < x) q.pop_back(); q.push_back(qqq); while (!qq.empty() && qq.back().w > x) qq.pop_back(); qq.push_back(qqq); } if (i == k - 1) { printf("%d", qq.front().w); Max[cnt++] = q.front().w; } } else { scanf("%d", &x); Deq qqq; qqq.idx = i; qqq.w = x; if (q.empty()) q.push_back(qqq); if (qq.empty()) qq.push_back(qqq); else { while (!q.empty() && q.back().w < x) q.pop_back(); q.push_back(qqq); while (!qq.empty() && qq.back().w > x) qq.pop_back(); qq.push_back(qqq); } while (q.front().idx < i + 1 - k) q.pop_front(); while (qq.front().idx < i + 1 - k) qq.pop_front(); printf(" %d", qq.front().w); Max[cnt++] = q.front().w; } } printf("\n"); for (int i = 0; i < cnt; i++) { i == 0 ? printf("%d", Max[i]) : printf(" %d", Max[i]); } return 0; }
洛谷题解:
直接用下标存进队列 手写双端队列
#include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<queue> #include<deque> #include<set> #include<map> #include<cmath> #include<stack> const double PI = acos(-1.0); #define INF 0x3f3f3f3f typedef long long ll; using namespace std; const int maxn = 1000005; int n, m; int q1[maxn], q2[maxn]; int a[maxn]; void Min_que() { int h = 1; //head int t = 0; //tail for (int i = 1; i <= n; i++) { while (h <= t && q1[h] + m <= i) h++; while (h <= t && a[i] < a[q1[t]]) t--; q1[++t] = i; if (i >= m) printf("%d ", a[q1[h]]); } printf("\n"); } void Max_que() { int h = 1; int t = 0; for (int i = 1; i <= n; i++) { while (h <= t && q2[h] + m <= i) h++; while (h <= t && a[i] > a[q2[t]]) t--; q2[++t] = i; if (i >= m) printf("%d ", a[q2[h]]); } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &a[i]); Min_que(); Max_que(); return 0; }
单调栈:
#include<iostream> #include<cstdio> #include<string> #include<algorithm> #include<queue> #include<set> #include<map> #include<cmath> #include<stack> const double PI = acos(-1.0); #define INF 0x3f3f3f3f typedef long long ll; using namespace std; struct S { int idx; int w; }; stack<S> s; int a[3000005]; vector<int> f; int main() { int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); for (int i = n - 1; i >= 0; i--) { if (i == n - 1) { f.push_back(0); s.push({ i,a[i] }); } else { if (s.empty()) { f.push_back(0); s.push({ i,a[i] }); } else { while (!s.empty()&&s.top().w <= a[i]) s.pop(); if (!s.empty()) f.push_back(s.top().idx+1); else f.push_back(0); s.push({ i,a[i] }); } } } for (auto it = f.rbegin(); it != f.rend(); it++) { if (it == f.rbegin()) printf("%d", *it); else printf(" %d", *it); } return 0; }