zoukankan      html  css  js  c++  java
  • 【ybtoj】【单调队列】最大矩阵

    题意

    分析

    由于放在单调队列章节里当然要考虑用单调队列做

    先说下最简单的思路:可以看作动态维护区间最小值,就是和单调队列模板---滑动窗口模型一样,维护一个单调上升的序列,再枚举区间长度,复杂度O(n2),期望得分40分

    再说进一步的思路:上一个思路为什么复杂度高,本质在于其枚举区间长度显然是麻烦了。既然对于一个区间,只关心它的区间最小值,那么在找到你一个区间最小值时,肯定是要它的长度越大越好,故不需要枚举区间长度

    上述想法反过来进行:对于每个点 i ,用 lst[i]nxt[i] 分别记录从 i 向左或向右走到的最远的点(的下一个点),使满足h[t]>=h[i]这样就只需要O(N)级别的复杂度了

    其实只是运用了单调队列的一个思路

    代码还有一些细节,注释写了

    图示如下

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int INF = 0x3f3f3f3f,N = 1e5+10;
    int a[N],n,k;
    int p[N],q[N],l=1,r;
    int cnt;
    int lst[N],nxt[N];//分别表示i向左,向右找到的不小于i的最远点 
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)
    		scanf("%d",&a[i]);
    /* 中间while更新不应该用t++、t--会超时 
    	lst[1]=1;
    	for(int i=2;i<=n;i++)
    	{
    		int t=i-1;
    		while(a[i]<=a[t]&&t>0) t--;
    		t++;
    		lst[i]=t;
    	}
    	nxt[n]=n;
    	for(int i=1;i<=n-1;i++)
    	{
    		int t=i+1;//写的时候要仔细想好边界条件能否都走到 
    		while(a[i]<=a[t]&&t<=n) t++;
    		t--;
    		nxt[i]=t;
    	}
    */
    	//lst,nxt的定义都往外移动了1位 
    	lst[1]=0;
    	for(int i=2;i<=n;i++)
    	{
    		int t=i-1;
    		while(a[i]<=a[t]&&t>0) t=lst[t];
    		lst[i]=t;
    	}
    	nxt[n]=n+1;
    	for(int i=n-1;i>=1;i--)
    	{
    		int t=i+1;
    		while(a[i]<=a[t]&&t<=n) t=nxt[t];
    		nxt[i]=t;
    	}
    	ll ans=0;
    	for(int i=1;i<=n;i++)
    		ans=max(ans,1LL*(nxt[i]-lst[i]-1)*a[i]);
    	printf("%lld",ans);
    	return 0;
    }
    
  • 相关阅读:
    C++Vector使用方法
    Struts2学习笔记1
    全排列算法及实现
    概率图模型(PGM)学习笔记(三)模式判断与概率图流
    SQLite的SQL语法
    马云入股恒大背后暗藏四大隐情?
    ListView的优化
    通过WriteProcessMemory改写进程的内存
    “富豪相亲大会”究竟迷失了什么?
    Java实现 蓝桥杯VIP 算法提高 密码锁
  • 原文地址:https://www.cnblogs.com/conprour/p/15054220.html
Copyright © 2011-2022 走看看