【FZYZ P1280 】【NOIP福建夏令营】矩形覆盖

Description

有N个矩形,矩形的底边边长为1,且均在X轴上,高度给出,第i个矩形的高为h[i],求最少需要几个矩形才能覆盖这个图形。

例如h = [3, 2, 4, 2]的图形如下:

容易发现,只需要3个矩形就能覆盖这个图形。

Input Format

第一行一个整数N。接下来1行包含N个正整数,为h[i]。

Output Format

输出一个整数表示最少需要几个矩形能覆盖这个图形。

Sample Input
10
2 3 2 4 2 1 3 4 3 2
Sample Output
7
Hint

对于所有数据,N<=100000,h[i] <= 100。

对于部分数据,N<=10;

对于部分数据,N<=100;

对于部分数据,N<=1000;

对于部分数据,h[i] <= 10;

题解

显然,若存在一个矩形的高度为x,则必然存在一个覆盖的矩形,其上边界高度为x.

所以,若所有h[i]各不相同,就要用N个矩形才能覆盖这个图形.

如果答案小于N,那么必然存在i,j(1<=i<j<=N),使得h[i]=h[j],且对任意k满足i<k<j,有h[k]>=h[i]且h[k]>=h[j](否则该覆盖矩形会超出图形的范围).

单调栈维护严格上升序列即可

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std; int n,ans;
int h[];
stack<int> q; int main()
{
int i,j;
scanf("%d",&n);
ans=n;
for(i=;i<=n;i++) scanf("%d",&h[i]);
q.push(h[]);
for(i=;i<=n;i++)
{
while(!q.empty()&&q.top()>=h[i])
{
if(q.top()==h[i]) ans--;
q.pop();
}
q.push(h[i]);
}
printf("%d",ans);
return ;
}

【洛谷P1901 】发射站

http://www.luogu.org/problem/show?pid=1901

题目描述

某地有 N 个能量发射站排成一行,每个发射站 i 都有不相同的高度 Hi,并能向两边(当 然两端的只能向一边)同时发射能量值为 Vi 的能量,并且发出的能量只被两边最近的且比 它高的发射站接收。

显然,每个发射站发来的能量有可能被 0 或 1 或 2 个其他发射站所接受,特别是为了安 全,每个发射站接收到的能量总和是我们很关心的问题。由于数据很多,现只需要你帮忙计 算出接收最多能量的发射站接收的能量是多少。

输入格式

第 1 行:一个整数 N;

第 2 到 N+1 行:第 i+1 行有两个整数 Hi 和 Vi,表示第 i 个人发射站的高度和发射的能量值。

输出格式

输出仅一行,表示接收最多能量的发射站接收到的能量值,答案不超过 longint。

输入样例:

3
4 2
3 5
6 10

输出样例:

7

数据规模

对于 40%的数据,1<=N<=5000;1<=Hi<=100000;1<=Vi<=10000;

对于 70%的数据,1<=N<=100000;1<=Hi<=2,000,000,000;1<=Vi<=10000;

对于 100%的数据,1<=N<=1000000;1<=Hi<=2,000,000,000;1<=Vi<=10000。

题解

单调栈维护找出向左(右)边的第一个比自己大的数。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std; long long h[],p[],sum[];
struct hh{int l,r;};
hh f[];
long long ans;
int n,cnt;
stack<int> s; int main()
{
int i,j;
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%lld%lld",&h[i],&p[i]);
s.push();
for(i=;i<=n;++i)
{
while(!s.empty() && h[i]>h[s.top()]) f[s.top()].r=i,s.pop();
s.push(i);
}
while(!s.empty()) s.pop();
s.push(n);
for(i=n-;i>=;--i)
{
while(!s.empty() && h[i]>h[s.top()]) f[s.top()].l=i,s.pop();
s.push(i);
} for(i=;i<=n;i++){sum[f[i].l]+=p[i]; sum[f[i].r]+=p[i];}
for(i=;i<=n;i++) ans=max(ans,sum[i]);
printf("%lld",ans);
return ; }

【POJ2823 】【FZYZ P1561】滑动窗口

http://poj.org/problem?id=2823

Description

给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表:

你的任务是找出窗口在各位置时的max value,min value.

Input Format

第1行n,k,第2行为长度为n的数组

Output Format

2行,第1行每个位置的min value,第2行每个位置的max value

Sample Input
8 3
1 3 -1 -3 5 3 6 7
Sample Output
-1 -3 -3 -3 3 3
3 3 5 5 6 7
Hint

20%:n<=500;

50%:n<=100000;

100%:n<=1000000;

题解

双端单调队列维护

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,k;
int a[],maxx[],minn[];
int q[]; int main()
{
int i,j,head=,tail=;
scanf("%d%d",&n,&k);
for(i=;i<=n;i++) scanf("%d",&a[i]); head=;tail=;q[++tail]=;
for(i=;i<=k;i++)
{
while(head<=tail&&a[q[tail]]<a[i]) tail--;
q[++tail]=i;
}
maxx[]=a[q[head]];
for(i=k+;i<=n;i++)
{
while(head<=tail&&a[q[tail]]<a[i]) tail--;
while(head<=tail&&i-q[head]>=k) head++;
q[++tail]=i;
maxx[i-k+]=a[q[head]];
} head=;tail=;
q[++tail]=;
for(i=;i<=k;i++)
{
while(head<=tail&&a[q[tail]]>a[i]) tail--;
q[++tail]=i;
}
minn[]=a[q[head]];
for(i=k+;i<=n;i++)
{
while(head<=tail&&a[q[tail]]>a[i]) tail--;
while(head<=tail&&i-q[head]>=k) head++;
q[++tail]=i;
minn[i-k+]=a[q[head]];
}
for(i=;i<=n-k+;i++) printf("%d ",minn[i]);printf("\n");
for(i=;i<=n-k+;i++) printf("%d ",maxx[i]);
return ;
}

【ZLD NOIP模拟题】序列

【问题描述】

有一个长度为n的非负整数序列,每次操作可以选择相邻的两个数,删去它们,然后在这个位置插入一个数,此次操作的代价定义为,求将这个序列长度变为1的最少代价。

【输入格式】

第一行为一个正整数n,表示序列的长度。

第二行有n个非负整数,表示这个序列。

【输出格式】

一行一个数,表示最少代价。

【输入输出样例】

seq.in

seq.out

3

1 2 3

5

【数据规模】

对于30%的数据,

对于50%的数据,

对于100%的数据,

题解

算法1:我们从左往右读入序列,用一个单调栈,当我们新加进去的数>栈顶时,那么便将栈顶的数拿去跟前一个或者当前的数合并(看哪个比较小),直到不满足这个条件,此时就把当前这个数塞入栈,最后注意一下栈中剩余的元素也是要合并的。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
int n;
long long ans;
int a[];
stack<int> q; int main()
{
int i,j,temp,in;
scanf("%d",&n);
for(i=;i<=n;i++) scanf("%d",&a[i]);
q.push();
for(i=;i<=n;i++)
{
if(!q.empty()&&q.top()>a[i])
{
q.push(a[i]);
continue;
}
while(!q.empty()&&q.top()<a[i])
{
q.pop();
if(a[i]>q.top()) ans+=(long long)q.top();
else ans+=(long long)a[i];
}
q.push(a[i]);
}
if(!q.empty()&&q.size()!=)
{
q.pop();
while(!q.empty())
{
if(q.size()==) goto hhh;
ans+=(long long)q.top();
q.pop();
}
}
hhh:;
printf("%lld",ans);
return ;
}

算法2:

标程做法。我们考虑相邻的两个数x,y,不妨设x>y,则我们先在x右端找一条最长的以y为左端点的区间,使区间内所有的数<=x。

然后呢我们将这些数合并起来,再与x合并,那么这个代价就是x了。

这下子做法就出来了,答案就是

代码略。

【NOIP数据结构专项】单调队列单调栈的更多相关文章

  1. 单调队列 && 单调栈

    单调队列 && 单调栈 单调队列 维护某个滑动区间的min or max,可用于dp的优化 以维护min为例,采用STL双端队列实现 每次加入元素x前 先检查队首元素==滑动后要删除的 ...

  2. 联赛模拟测试18 A. 施工 单调队列(栈)优化DP

    题目描述 分析 对于 \(Subtask\ 1\),可以写一个 \(n^3\) 的 \(DP\),\(f[i][j]\) 代表第 \(i\) 个建筑高度为 \(j\) 时的最小花费,随便转移即可 时间 ...

  3. 数据结构录 之 单调队列&单调栈。

    队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇的队列和栈的扩展. 其中最出名的应该是优先队列吧我觉得,然后还有两种比较小众的扩展就是单调 ...

  4. 数据结构录 之 单调队列&单调栈。(转)

    http://www.cnblogs.com/whywhy/p/5066306.html 队列和栈是很常见的应用,大部分算法中都能见到他们的影子. 而单纯的队列和栈经常不能满足需求,所以需要一些很神奇 ...

  5. 小Z爱序列(NOIP信(sang)心(bin)赛)From FallDream(粗制单调队列&单调栈的算法解析)

    原题: 小Z最擅长解决序列问题啦,什么最长公共上升然后下降然后上升的子序列,小Z都是轻松解决的呢. 但是小Z不擅长出序列问题啊,所以它给了你一道签到题. 给定一个n个数的序列ai,你要求出满足下述条件 ...

  6. 单调队列&单调栈

    单调队列 例题: Poj 2823给定一个数列,从左至右输出每个长度为m的数列段内的最小数和最大数.数列长度:N<=106,m<=N 对于单调队列,我们这样子来定义: 1.维护区间最值 2 ...

  7. 大视野 1012: [JSOI2008]最大数maxnumber(线段树/ 树状数组/ 单调队列/ 单调栈/ rmq)

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 9851  Solved: 4318[Submi ...

  8. POJ 3494 Largest Submatrix of All 1’s 单调队列||单调栈

    POJ 3494 Largest Submatrix of All 1’s Description Given a m-by-n (0,1)-matrix, of all its submatrice ...

  9. 单调队列&单调栈归纳

    单调队列 求长度为M的区间内的最大(小)值 单调队列的基本操作,也就是经典的滑动窗口问题. 求长度为M的区间内最大值和最小值的最大差值 两个单调队列,求出长度为M的区间最大最小值的数组,分别求最大最小 ...

随机推荐

  1. day25 CMDB(1)

    CMDB项目介绍 参考地址: http://www.cnblogs.com/wupeiqi/articles/4556300.html http://www.cnblogs.com/wupeiqi/a ...

  2. hdu4324 dfs

    scanf("%1d")这种好像很慢. #include<stdio.h> #include<string.h> #define maxn 2010 str ...

  3. ORA-03113: end-of-file on communication channel 解决方案

    Oracle启动时报如下错误:ORA-03113: end-of-file on communication channel  解决方案如下:1.查看orcle启动日志,确定具体是什么原因引起的错误. ...

  4. 安装完django验证是否安装成功&&运行项目

    1.验证是否成功安装django 上图证明安装成功 2.打开客户端的pycharm,在terminal中打开窗体,什么都没输入,运行下面的命令 python manage.py runserver 在 ...

  5. JPA中id前面有空格导致的"Column 'id' not found"问题

    问题背景 昨晚有个同事发生了一个神奇的问题,一如既往的问题,一如既然的用我写的BEJSON-JAVA代码生成器生成,却发现一直提示Column 'id' not found.这就很TM神奇了 2018 ...

  6. 二分查找 Day08

    package com.sxt.arraytest2; /* * 二分查找 前提:有序 */ public class TestBinarySearch { public static void ma ...

  7. JavaScript原型链中toString()方法输出alert()和console.log()得到不同的结果

    <script language="javascript"> function myObj(){ var total = 0; } myObj.prototype.ad ...

  8. YUI css reset

    *{ margin:0; padding:0; } 以前写CSS都会在会在样式的开头部分添加上述的内容,今天才发现这种写法很不友好,会导致很多样式显示问题,所以并不适合所有的浏览器. 下面的是雅虎的c ...

  9. oracle函数 LTRIM(c1,[,c2])

    [功能]删除左边出现的字符串 [参数]C1 字符串 c2 追加字符串,默认为空格 [返回]字符型 [示例] SQL> select LTRIM('   gao qian jing',' ') t ...

  10. @hdu - 6428@ Problem C. Calculate

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 A, B, C,求: \[\sum_{i=1}^{A}\s ...