HZNU-ACM寒假集训Day10小结 单调栈-单调队列
数据结构往往可以在不改变主算法的前提下题高运行效率,具体做法可能千差万别,但思路却是有规律可循
经典问题:滑动窗口 单调队列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[]; int main() {
int n, k;
int x;
int cnt = ;
scanf("%d%d", &n, &k);
for (int i = ; 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 - ) {
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 + - k) q.pop_front();
while (qq.front().idx < i + - k) qq.pop_front();
printf(" %d", qq.front().w);
Max[cnt++] = q.front().w;
}
}
printf("\n");
for (int i = ; i < cnt; i++) {
i == ? printf("%d", Max[i]) : printf(" %d", Max[i]);
}
return ;
}
洛谷题解:
直接用下标存进队列 手写双端队列
#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 = ;
int n, m;
int q1[maxn], q2[maxn];
int a[maxn]; void Min_que() {
int h = ; //head
int t = ; //tail
for (int i = ; 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 = ;
int t = ;
for (int i = ; 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 = ; i <= n; i++) scanf("%d", &a[i]);
Min_que();
Max_que();
return ;
}
单调栈:
#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[];
vector<int> f; int main() {
int n;
scanf("%d", &n);
for (int i = ; i < n; i++) scanf("%d", &a[i]);
for (int i = n - ; i >= ; i--) {
if (i == n - ) {
f.push_back();
s.push({ i,a[i] });
}
else {
if (s.empty()) {
f.push_back();
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+);
else f.push_back();
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 ;
}
HDU 1506
题目题意:题目给了n个矩形的高度,问最大连续矩形的公共面积(底乘以这段连续矩形中最短的高度),每个矩形的底是1
感觉有点像贪心,想了很久没想出单调栈的做法 事实上需要维护一个递增的矩形,每次出栈维护最大值
#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 = ;
int a[maxn];
int s[maxn], w[maxn]; ll ans; int main() {
int n;
while (scanf("%d", &n) != EOF) {
if (!n) break;
int p = ;
ans = ;
for (int i = ; i <=n; i++) scanf("%d", &a[i]);
a[n+] = ; //注意设置a[0]=0,a[n+1]=0,因为最后一个也可能出栈
for (int i = ; i <= n+; i++) {
if (a[i] > s[p]) s[++p] = a[i], w[p] = ; //维护单调递增的栈
else {
int wid = ;
while (s[p] > a[i]) {
wid += w[p];
ans = max(ans, (ll)wid * s[p]); //core
p--;
}
s[++p] = a[i];
w[p] = wid + ;
}
}
printf("%lld\n", ans);
}
return ;
}
POJ 3494 求一个0-1矩阵中全为1的最大子矩阵。
#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 = ;
int mp[maxn][maxn];
int h[maxn][maxn];
int L[maxn], R[maxn], st[maxn]; int main() {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = ; i < n; i++) {
for (int j = ; j < m; j++) {
scanf("%d", &mp[i][j]);
}
}
for (int i = ; i < m; i++) {
int high = ;
for (int j = n - ; j >= ; j--) {
if (mp[j][i]) high++;
else high = ;
h[j][i] = high;
}
}
int ans = ;
for (int i = ; i < n; i++) {
int pos = ;
for (int j = ; j < m; j++) {
while (pos > && h[i][st[pos - ]] >= h[i][j]) pos--;
L[j] = pos == ? : st[pos - ] + ;
st[pos++] = j;
}
pos = ;
for (int j = m - ; j >= ; j--) {
while (pos > && h[i][st[pos - ]] >= h[i][j]) pos--;
R[j] = pos == ? m - : st[pos - ] - ;
st[pos++] = j;
}
for (int j = ; j < m; j++) {
ans = max(ans, h[i][j] * (R[j] - L[j] + ));
}
}
printf("%d\n", ans);
}
return ;
}
HZNU-ACM寒假集训Day10小结 单调栈-单调队列的更多相关文章
- HZNU-ACM寒假集训Day10小结 树-树形DP
树形DP 加分二叉树 洛谷P1040 注意中序遍历的特点:当根节点编号k时,编号小于k的都在其左子树上,编号大于k的都在右子树 转移方程 f[i,j]=max{f[i,k-1]*f[k+1,j]+d[ ...
- 小结:单调栈 & 单调队列
概要: 对于维护信息具有单调性的性质或者问题可以转化为具有单调性质的模型的题,我们可以考虑用单调栈或单调队列. 技巧及注意: 技巧很多,只要能将问题转化为单调性问题,就好解决了. 当维护固定长度的单调 ...
- 中南大学2019年ACM寒假集训前期训练题集(基础题)
先写一部分,持续到更新完. A: 寒衣调 Description 男从戎,女守家.一夜,狼烟四起,男战死沙场.从此一道黄泉,两地离别.最后,女终于在等待中老去逝去.逝去的最后是换尽一生等到的相逢和团圆 ...
- POJ 3250 Bad Hair Day --单调栈(单调队列?)
维护一个单调栈,保持从大到小的顺序,每次加入一个元素都将其推到尽可能栈底,知道碰到一个比他大的,然后res+=tail,说明这个cow的头可以被前面tail个cow看到.如果中间出现一个超级高的,自然 ...
- 单调栈&单调队列入门
单调队列是什么呢?可以直接从问题开始来展开. Poj 2823 给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数. 数列长度:\(N <=10^6 ,m<=N\) 解法① ...
- 单调栈&单调队列学习笔记!
ummm,,,都是单调系列就都一起学了算了思想应该都差不多呢qwq 其实感觉这俩没有什么可说的鸭QAQ就是维护一个单调的东西,区别在于单调栈是一段进一段出然后单调队列是一段进另一段出?没了 好趴辣重点 ...
- 单调栈&单调队列
最近打了三场比赛疯狂碰到单调栈和单调队列的题目,第一,二两场每场各一个单调栈,第三场就碰到单调队列了.于是乎就查各种博客,找单调栈,单调队列的模板题去做,搞着搞着发现其实这两个其实是一回事,只不过利用 ...
- [CSP-S模拟测试]:Cover(单调栈++单调队列+DP)
题目传送门(内部题126) 输入格式 第一行两个个整数$n,m$表示区间的长度与彩灯的数量. 接下来$m$行,每行三个整数$l_i,r_i,a_i$表示一条彩灯能够覆盖的区间以及它的美观程度. 输出格 ...
- 中南大学2019年ACM寒假集训前期训练题集(入门题)
A: 漫无止境的八月 Description 又双叒叕开始漫无止境的八月了,阿虚突然问起长门在这些循环中团长哪几次扎起了马尾,他有多少次抓住了蝉等等问题,长门一共回复n个自然数,每个数均不超过1500 ...
随机推荐
- 题解 CF1131C 【Birthday】
CF大水题 题意:给你n个人,他们的身高是a[i],让你将这几个人排成一个环,使得他们两两之间身高差的和最小. 思路:简单到爆了,恶意评分上蓝.直接将那几个人排个序,然后按序左右放就行了,也就是说1号 ...
- upload-labs-env文件上传漏洞 1-10关
Pass-01 首先先看源码: function checkFile() { ].value; if (file == null || file == "") { alert(&q ...
- 云时代架构阅读笔记十五——之前碰到的Java面试题
1.一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 可以有多个类,但只能有一个public的类,并且public的类名必须与文件名相一致. 2.Java有 ...
- Day7 - K - Biorhythms POJ - 1006
Some people believe that there are three cycles in a person's life that start the day he or she is b ...
- JDK8中的HashMap实现原理及源码分析
大纲 一.什么是Hash?什么是HashMap? 二.HashMap的内部实现机制 1.HashMap基本元素 ①DEFAULT_INITIAL_CAPACITY&MAXIMUM_CAPACI ...
- HTTP和HTTPS的区别及HTTPS加密算法
一.HTTP和HTTPS的概念 HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传 ...
- mapper语句的一些问题,union连表查询和mapper中根据条件不同采用不同语句的查询问题
根据业务要求,不同表查出来的内容天需要一起展示出来,并且还有分页之类的,不同表查询字段也不完全相同,这样就有一个问题,不同表如何接合在一起,不同字段怎么办? 这个问题就需要用到union联合查询,并将 ...
- poj3405 Corporate Identity
和上一个1226一样吧,这个还不用翻转 然而本蒟蒻还是写不对,WA一片天,不知道自己搞什么,自从去了长沙感觉就是坑啊 while(1) iq--; /*#include <cstdio> ...
- IPsec_crypto[6]次配置
IPsec_crypto[6]次配置: ①.①:crypto isakmp enbale——启用ISAKMP ②.②:crypto isakmp policy 10——创建一个策略组 ③:encryp ...
- js 运行机制简单了解
一.如何理解 JS 的单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. JavaScrip ...