【DP/单调栈】关于单调栈的一些题目(codevs 1159,codevs 2673)



题目描述 Description

  这个月的pku月赛某陈没有参加,因为当时学校在考试[某陈经常逃课,但某陈还没有强大到考试也可以逃掉的程度].何况,对于北大校赛,水牛通常是没有什么希望考得好的[事实上某陈最好成绩是仅A了一道题].

  某陈郁闷.接下来他又将沉浸在无穷尽的刷题中,每天面对各种颜色的Status--WA,TLE,RE,甚至还有MLE,CE,PE什么什么的,他无比期待蓝色的AC.

  话说RP爆发的某陈弄到了很久以后某次pku月赛的某题的题目和输入数据,如下所示.

  输入数据包括n个测试点,每个点都有一个最大可获得的分数m.选手需要选定任意3个整数,i,j,m0,1<=i<=j<=n,代表选手选择的测试点范围是从第i个到第j个,每个测试点的期望分数均为m0.本题为Special Judge[特殊评测],评测时系统将遍历标号从i到j的测试点,对于被遍历的每一个测试点,如果当前测试点的m小于m0,则终止评测并判定选手得分为0,否则系统将为选手得分加上m0[系统初始化选手得分为0].若最终选手得分与可能的最大得分相同,那么选手就AC了这题.

  某陈已经为本题写了好久的代码,现在他需要知道本题可能的最大得分,来验证他的输出是否为最优解.请计算选手的最大得分,给某陈一个打表的机会~

  [某陈:神啊..请赐予我力量吧..我需要一次华丽丽的AC..]

输入描述 Input Description

  输入文件第一行为一个整数n,如题目描述中的含义.0<n<=10^6

  接下来的一行包括n个整数m,如题目描述中的含义.0<=m<2^31

输出描述 Output Description

  输出文件包含一个整数,为题目描述中的最大得分.


  force1:暴力枚举法,O(n^2),不过显然过不了。

  2:单调栈:首先来说一说单调栈

  单调栈与单调队列很相似。首先栈是后进先出的,单调性指的是严格的递增或者递减。

  单调栈有以下两个性质:

  1、若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。

  2、越靠近栈顶的元素越后进栈。

  单调栈与单调队列不同的地方在于栈只能在栈顶操作,因此一般在应用单调栈的地方不限定它的大小,否则会造成元素无法进栈。

  元素进栈过程:对于单调递增栈,若当前进栈元素为e,从栈顶开始遍历元素,把小于e或者等于e的元素弹出栈,直接遇到一个大于e的元素或者栈为空为止,然后再把e压入栈中。对于单调递减栈,则每次弹出的是大于e或者等于e的元素。

  一个单调递增栈的例子:

  进栈元素分别为3,4,2,6,4,5,2,3

  3进栈:(3)

  3出栈,4进栈:(4)

  2进栈:(4,2)

  2出栈,4出栈,6进栈:(6)

  4进栈:(6,4)

  4出栈,5进栈:(6,5)

  2进栈:(6,5,2)

  2出栈,3进栈:(6,5,3)

  以上左端为栈底,右端为栈顶。(摘自http://blog.csdn.net/alongela/article/details/8227707)

  之后这题就可以用单调栈来做啦。

  然后就是对于比栈顶元素大的,我们就直接入栈。

  对于比栈顶元素小的,我们把比它小的元素出栈,且把最大值更新((当前元素下标-出栈元素进栈时间)*出栈元素),最后进栈, 进栈时间设为最后一个元素出栈的时间(自己思考为什么- -)。

  O(n)一遍过。。

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5
 6 using namespace std;
 7
 8 int stack[1000001],top=0,time[1000001];
 9
10 int main()
11 {
12     int n,x;
13     long long mx=0;
14     scanf("%d",&n);
15     for(int i=1;i<=n+1;i++)
16     {
17         int d=i;
18         if(i<=n)scanf("%d",&x);
19         else x=-1;
20         if(!top)stack[++top]=x,time[top]=1;
21         while(x<stack[top]&&top!=0)
22         {
23             long long sb=(long long)stack[top]*(i-time[top]);
24             mx=max(mx,sb);
25             d=time[top];
26             top--;
27         }
28         if(x>stack[top])stack[++top]=x,time[top]=d;
29     }
30     printf("%lld",mx);
31     return 0;
32 }



题目描述 Description

  在一个0,1方阵中找出其中最大的全0子矩阵,所谓最大是指O的个数最多。

输入描述 Input Description

  输入文件第一行为整数N,其中1<=N<=2000,为方阵的大小,紧接着N行每行均有N个0或1,相邻两数间严格用一个空格隔开。

输出描述 Output Description

  输出文件仅一行包含一个整数表示要求的最大的全零子矩阵中零的个数。



  force1:枚举每个矩阵的左上右下两点,判断里面的元素是否全为0,复杂度0(n6),可以加个最优型剪枝加速一下。。

  2.首先我们用f[i][j]来表示第i行第j列以上的元素有几个0.

  然后我们发现,这不就是在每一列求第一题吗。。

  好了。。就是这样,记得当g[i][j]为1是f[i][j]=0,

  f[i][j]可以优化成1维的!

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5
 6 using namespace std;
 7
 8 int num[2001],stack[2001],time[2001],top=0,ans=0,n;
 9
10 bool g[2001];
11
12 void work()
13 {
14     top=0;
15     memset(stack,0,sizeof(stack));
16     memset(time,0,sizeof(time));
17     for(int i=1;i<=n+1;i++)
18     {
19         int d=i,x=num[i];
20         if(i==n+1)x=-1;
21         if(!top)stack[++top]=x,time[1]=1;
22         while( stack[top]>x && top!=0 )
23         {
24             int sb=stack[top]*(i-time[top]);
25             ans=max(ans,sb);
26             d=time[top];
27             top--;
28         }
29         if(stack[top]<x||x==0)stack[++top]=x,time[top]=d;
30     }
31 }
32
33 int main()
34 {
35     int x;
36     scanf("%d",&n);
37     for(int i=1;i<=n;i++)
38     {
39         for(int j=1;j<=n;j++)
40         {
41             scanf("%d",&x);
42             g[j]=x;
43             if(!g[j])num[j]++;
44             else num[j]=0;
45         }
46         work();
47     }
48     printf("%d",ans);
49     return 0;
50 }


  第三题题目我手贱删了。。

  讲讲大致题意把。。

  就是说给你一个矩阵,有各种数字,求满足每个矩阵的左上加右上小于等于左下加右上且它的子矩阵也满足条件的矩阵的最大面积,矩阵的最小长,宽为2.

  force1及优化就不说了。。

  正解:把所有的2*2矩阵缩成一个小矩阵。。满足条件就是0,不满足就是1.(根据个人喜好)

  然后就是喜闻乐见的第二题解法了。。记得答案是(当前元素下标-出栈元素进栈时间+1)*(出栈元素+1)。。

  代码也删了。。大家自己脑补吧。。

  

时间: 2024-10-12 21:47:23

【DP/单调栈】关于单调栈的一些题目(codevs 1159,codevs 2673)的相关文章

codeforce1029B B. Creating the Contest(简单dp,简单版单调栈)

B. Creating the Contest time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You are given a problemset consisting of nn problems. The difficulty of the ii-th problem is aiai. It is guaranteed t

单调栈以及单调队列

单调栈: 定义: 栈内的元素,按照某种方式排列下(单调递增或者单调递减),如果新入栈的元素破坏了单调性,就弹出栈内元素,直至满足单调性. 作用:单调栈可以找到从左/右遍历第一个比它大/小的元素的位置.时间复杂度为O(N): 实现方式:(以维护单调递增栈为例) 进栈操作:每次进入栈时,先检验栈顶元素和进栈元素的大小,如果小于,那么直接入栈:否则,大于等于进栈元素的出栈,直到栈空或者栈顶元素小于入栈元素. 例如:3 8 2 3 1 初始时刻栈为空,3入栈.......................

浅谈单调队列、单调栈

       初谈这个话题,相信许多人会有一种似有所悟,但又不敢确定的感觉.没错,这正是因为其中"单调"一词的存在,所谓单调是什么,学过函数的people都知道单调函数或者函数的单调性,直白一点说单调就是一直增或一直减.例如:1,3,5,9就是一个单调增数列,数列中不存在后一个数比前一个数小的现象.那么同样,在这里谈到的话题也有类似特点.        先说一下单调队列吧!      单调队列,就是一个符合单调性质的队列,它同时具有单调的性质以及队列的性质.他在编程中使用频率不高,但却

hdu4193---Non-negative Partial Sums(单调队列 or 单调栈)

Problem Description You are given a sequence of n numbers a0,-, an-1. A cyclic shift by k positions (0<=k<=n-1) results in the following sequence: ak ak+1,-, an-1, a0, a1,-, ak-1. How many of the n cyclic shifts satisfy the condition that the sum of

单调队列,单调栈相关

说起这个话题,应该很多人会有一种似有所悟,但又不敢确定的感觉. (我差不多就是那样) 没错,这正是因为其中“单调”一词的存在. 那么单调是什么? 学过函数的人都知道单调函数或者函数的单调性吧 其实直白一点说单调,就是一直增或一直减. eg:1,3,5,9就是一个单调增数列,数列中不存在后一个数比前一个数小的现象. 那么同样,在这里谈到的话题也有类似特点. (一)单调队列 其实就是一个符合单调性质的队列,但它同时具有单调的性质以及队列的性质. 使用频率不算高,但却占有至关重要的地位.它的作用很简单

单调队列与单调栈用法详解

1.单调栈 单调栈是指一个栈内部的元素具有严格单调性的一种数据结构,分为单调递增栈和单调递减栈. 其具有以下两个性质: 1,满足栈底到栈顶的元素具有严格单调性. 2,满足栈的先进后出特性,越靠近栈顶的元素越后出栈. 单调队列同理,其严格单调性与单调栈相同. 但该队列中的元素满足先进先出特性,越靠近队列头的元素越先出队. 原文地址:https://www.cnblogs.com/xiefengze1/p/8495272.html

单调栈与单调队列

单调栈 特点 栈内的元素单调递增或者单调递减,可以在\(O(n)\)的时间内求出数列中所有数的左边或右边第一个比其大或小的元素,总时间复杂度为\(O(n)\) 例子 单调栈中一般存索引 一个单调递增栈s = [0, 10, 20 ,t]代表栈中a[1]~a[9]的元素大于a[10]的元素,索引为a[11]~a[19]的元素大于a[20]的元素... 这样我们可以发现在a[10]左边第一个比a[10]的数为a[0],在a[20]左边第一个比a[20]的数为a[10]... 如何实现呢? 每次有元素

单调队列、单调栈、优先队列模板

目录 单调栈.单调队列及优先队列 1.单调队列 2.单调栈 3.优先队列 单调栈.单调队列及优先队列 1.单调队列 单调队列的描述:指队列中元素之间关系具有单调性,而且队首和队尾都可以出队,但是只有队尾可以进行入队操作.其重要作用是找到前n个后者后n个数的最值. 其具体操作是:假设单调队列是单调递减队列,假设在插入元素v时,将队列尾部的元素同v比较,如果队列尾部的元素不大于元素v,我们直接删除队尾元素,再将队尾元素与v比较,直至队尾元素比v大,这个时候我们将v插入队尾.其实现代码如下: int

第三章:1.栈和队列 -- 栈的表示及实现

前言: 栈和队列 是两种重要的线性结构.从数据结构角度来看,栈和队列也是线性表,它的特殊性在于其操作是线性表的子集,是操作受限的线性表,因此可以称作限定性的数据结构. (限定性:如.人为的规定线性表只能从表尾插入和删除结点数据元素,那么这样的线性表就是栈) 目录: 1.栈 2.栈的应用举例 3.栈与递归的实现 4.队列 5.离散事件模型 正文: 栈的定义 栈(stack) 如上所说,就是限定只能在表尾进行插入和删除的线性表.表尾 称为 栈顶(top), 表头 称为 栈底 (bottom),没有数