目录
回顾上期
先言
在上期中,我们留下了4道关于【单调队列】的题目,今天就来解答这4道题目
标准程序
一:滑动窗口
#include<iostream>
#include<cstdio>
#include<cstring>
#include<deque>
using namespace std;
deque<int> q_max,q_min;
int n,k,a[1000001];
int b[1000001],c[1000001];
void insert(int,bool);
void init();
void work();
int main()
{
//freopen("window6.in","r",stdin);
//freopen("window.out","w",stdout);
init();
work();
return 0;
}
void init()
{
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
}
void work()
{
for(int i=1;i<k;i++)
{
insert(i,0);
insert(i,1);
}
for(int i=k;i<=n;i++)
{
insert(i,0);
insert(i,1);
while(!q_max.empty()&&q_max.front()<i-k+1) q_max.pop_front();
while(!q_min.empty()&&q_min.front()<i-k+1) q_min.pop_front();
b[i]=a[q_max.front()];
c[i]=a[q_min.front()];
}
for(int i=k;i<n;i++) cout<<c[i]<<' ';cout<<c[n]<<endl;
for(int i=k;i<n;i++) cout<<b[i]<<' ';cout<<b[n]<<endl;
}
void insert(int x,bool f)
{
if(f)
{
while(!q_max.empty() && a[q_max.back()]<=a[x]) q_max.pop_back();
q_max.push_back(x);
}
else
{
while(!q_min.empty() && a[q_min.back()]>=a[x]) q_min.pop_back();
q_min.push_back(x);
}
}
二:最大连续和
#include <iostream>
using namespace std;
int b[1005], a[1005];
const int INF = 1000000000;
int main(){
int n, MAX;
while(cin >> n && n){
b[0] = 0;
MAX = -INF;
for(int i = 1; i <= n; ++i){
cin >> a[i];
b[i] = a[i]+b[i-1];
}
for(int i = 0; i < n; ++i)
for(int j = i+1; j <= n; ++j)
if(b[j]-b[i] > MAX)
MAX = b[j]-b[i];
cout << MAX << endl;
}
return 0;
}
三:礼物(本题在OJ上需要加加速代码)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int f[3][160][160][160],ans=0,que[220],p,q,r;
void init()
{
char ch[160];
int i,j,k;
scanf("%d%d%d\n",&p,&q,&r);
for (i=1;i<=q;i++)
for (j=1;j<=p;j++)
{
scanf("%s",&ch);
for (k=1;k<=r;k++)
{
if (ch[k-1]=='N')
{
f[0][i][j][k]=1;
f[1][j][i][k]=1;
f[2][k][i][j]=1;
}
}
}
}
void work(int p1,int q1,int r1,int tmp)
{
int i,j,k,tail=0;
for (i=1;i<=p1;i++)
for (j=1;j<=q1;j++)
for (k=1;k<=r1;k++)
if (f[tmp][i][j][k]==1)
f[tmp][i][j][k]=min(f[tmp][i][j-1][k-1],min(f[tmp][i][j][k-1],f[tmp][i][j-1][k]))+1;
for (i=1;i<=q1;i++)
for (j=1;j<=r1;j++)
{
memset(que,0,sizeof(que));
tail=0;
for (k=1;k<=p1+1;k++)
{
while (f[tmp][k][i][j]<=f[tmp][que[tail]][i][j]&&tail>0)
{
ans=max(ans,4*f[tmp][que[tail]][i][j]*(k-que[tail-1]-1));
tail--;
}
que[++tail]=k;
}
}
}
int main()
{
init();
work(q,p,r,0);
work(p,q,r,1);
work(r,q,p,2);
printf("%d",ans);
return 0;
}
四:良好的感觉
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <deque>
using namespace std ;
int n,i,j,l,r,a[100002],q[100002],ll[100002],rr[100002];
long long maxn,s[100002];
int main()
{
//freopen("feelgood.in","r",stdin);
//freopen("feelgood.out","w",stdout);
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
l=1;r=0;
memset(ll,0,sizeof(ll));
memset(rr,0,sizeof(rr));
memset(q,0,sizeof(q));
for(i=1;i<=n+1;i++)
{
while(a[i]<a[q[r]]&&l<=r)
rr[q[r--]]=i-1;
q[++r]=i;
}
l=1;r=0;
memset(q,0,sizeof(q));
for(i=n;i>=0;i--)
{
while(a[i]<a[q[r]]&&l<=r)
ll[q[r--]]=i+1;
q[++r]=i;
}
maxn=0;
for(i=1;i<=n;i++)
if((s[rr[i]]-s[ll[i]-1])*a[i]>maxn)
maxn=(s[rr[i]]-s[ll[i]-1])*a[i];
cout<<maxn;
}
笔记
在本期中,我们列出了STL表中的几个重点部分,供大家学习!练习题目将在下期发布哦!
STL标准库的组成
•
STL由六个主要部分组成:空间配置器(allocator),适配器(adapters),
容器(container),迭代器(iterator)
,仿函数(functors)与算法(algorithm)。
•
STL的一个基本理念就是将数据与操作分离,数据由容器类别加以管理,操作则由可定制地算法定义,迭代器在两者之间充当粘合剂。
•
STL是C++标准库的一部分,它包括一组通用的模板类和函数,用于处理常见的编程任务,如数据存储、搜索、排序和迭代。STL的目标是提供高性能、可复用和可移植的代码,使开发者能够更加高效地编写C++程序。
STL标准模板库-容器
序列容器 | 关联容器 | 无序容器 |
vector | set | unordered_set(c++11) |
list | multiset | unordered_multise(c++11) |
deque | map | multiset_map(c++11) |
arry(c++11) | multimap | unordered_multimap(c++11) |
foward_list(c++11) |
STL标准模板库-迭代器
•
迭代器的作用是将容器与算法联系起来,起着粘合剂地作用,几乎STL提供的所有算法都是通过迭代器存取元素实现的。
•
STL共有输入迭代器,输出迭代器,正向迭代器,双向迭代器与随机访问迭代器共五种类型的迭代器,使用迭代器访问容器元素更简单,易用,且代码更加紧凑,简洁。
•
具体用法稍后再详细介绍
动态数组vector
•
定义:
vector <int> v;//
创建一个名字叫
v
,变量类型
int
的
vector
•
首地址:
v.begin
()
•
尾地址:
v.end
()
•
容器元素个数:
v.size
()
•
插入元素
1
:
v.push_back
(x);
//
在
v
的末尾插入一个
x
•
插入元素
2
:
v.insert
(
it,x
);//
在
v
中,位置
it
的后面插入一个
x
•
删除元素:
v.
erase(
it
)
//
在
v
中,删除位置
it
的元素
•
遍历1(for循环)
:
•
for(
size_t
i
=0;i<
v.size
();
i
++)
•
cout
<<v[
i
]<<" ";
•
遍历2(迭代器)
:
•
vector<int>::iterator it=
v.begin
();
•
while(it!=
v.end
()){
•
cout
<<*it<<” “;
•
++it;
•
}
集合set
•
定义:
set <int> v;//
创建一个名字叫
v
,变量类型
int
的
set
•
首地址:
v.begin
()
尾地址:
v.end
()
容器元素个数:
v.size
()
•
插入元素:
v.insert
(x);//
在
v
中插入一个
x
•
删除元素:
v.
erase(
it
)
/
v.
erase(
x
)
•
//
在
v
中,删除位置
it
的元素,或者删除值为
x
的元素
•
查找元素:
•
auto lower=
v
.lower_bound(2); // 不小于 2 的第一个元素
•
auto upper=
v
.upper_bound(3); // 大于 3 的第一个元素
•
遍历(迭代器)
:
•
set<int>::iterator it=
v.begin
();
•
while(it!=
v.end
()){
•
cout
<<*it<<” “;
•
++it;
•
}
或者
•
for(
set<int>::iterator it=
v.begin
();it!=
v.end
();++it;
)
•
cout
<<*it<<” “;
集合(元素可重复)multiset
•和set相比,元素可以重复
双端队列duque
•
定
义:duque
<int> v;//
创建一个名字叫v,变量类型int的duque
•
返回队列v开头的元素:v.front
()
•
返回队列v末尾的元素:v.back
()
•
容器元素个数:v.size
()
•
在队列
v
的末尾添加一个元素
x
:
v.
push_back(
x
)
•
在队列
v
的开头添加一个元素
x
:
v.
push_front(
x
)
•
移除队列
v
末尾的元素
x
:
v.
pop_back(
x
)
•
移除队列
v
开头的元素
x
:
v.
pop_front(
x
)
链表list
•
定
义:list
<int> v;//
创建一个名字叫v,变量类型int的list
•
返回v开头的元素:v.front
()
•
返回v末尾的元素:v.back
()
•
容器元素个数:v.size
()
•
在
v
的末尾添加一个元素
x
:
v.
push_back(
x
)
•
在
v
的开头添加一个元素
x
:
v.
push_front(
x
)
•
在位置
it
的前面添加一个元素
x
:
v.insert
(
it,x
)
•
移除
v
末尾的元素
x
:
v.
pop_back(
x
)
•
移除
v
开头的元素
x
:
v.
pop_front(
x
)
•
删除位置
it
的元素:
v.erase
(it)
•
遍历(迭代器):
•
list<int>::iterator it=
v.begin
();
•
while(it!=
v.end
()){
•
cout
<<*it<<” “;
•
++it;
•
}
或者
•
for(
list<int>::iterator it=
v.begin
();it!=
v.end
();++it;
)
•
cout
<<*it<<” “;
映射map
•
定义:
map<
int,int
> v;//
创建一个名字叫
v
,
int->int
的
map
•
首地址:
v.begin
()
•
尾地址:
v.end
()
•
容器元素个数:
v.size
()
•
插入元素:
v.insert
(
make_pair
(
x,y
));
mp
[x]=y;(
把
map
当大数组用
)
•
//在v中,插入一个x->y的映射
•
删除元素:
v.
erase(
it)
v.
erase(
x)
•
//
在
v
中,删除位置
it
的映射
或
删除键值为
x
的映射
•
遍历(迭代器):
•
map<int>::iterator it=
v.begin
();
•
while(it!=
v.end
()){
•
cout
<<it->first<<” “<<it->second<<” “;
•
++it;
•
}
或者
•
for(map<int>::iterator it=
v.begin
();it!=
v.end
();++it;)
•
cout
<<it->first<<” “<<it->second<<” “;
•
映射(元素可重复)multimap
•和map相比,元素可以重复