• 单调栈&单调队列入门


    此文持续更新。

    啊今下午形势政策看看了

    这个东西,发现我要想好好施展几何得先精通单调栈单调队列。

    然后就计划刷刷水题。结果打了一晚上游戏。

    又认识了一个辅助妹子,难道我的过去要被画上句号,开始一段新的恋情了吗?还记得两年前,也是那样一个普通的夜晚,也是小炮和露露,

    我的小炮特别浪,总是喜欢w跳脸,但她却总是能跟上我,在我跳脸的时候击飞别人,被控的时候坩埚秒解,被追的时候预判救赎,要死的时候闪现给盾,

    然而到了后来,我在说什么啊??? 

    完蛋了啊,要被队友捅死了啊。

    poj2796 

    定义一段区间的权值为最小值乘以区间和,求给定数组的最大权值。

    找到以每个数为最小值的区间的端点。

     1 #include <cstdio>
     2 #include <iostream>
     3 using namespace std;
     4 typedef long long ll;
     5 const int N = 1e5+5;
     6 ll n,a[N],pre[N],las[N],sum[N],q[N];
     7 int main(){
     8     scanf("%lld",&n);
     9     for(int i=1;i<=n;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
    10     int l=0,r=0;
    11     for(int i=1;i<=n;i++){
    12         while (r>0&&a[q[r]]>a[i]){
    13             las[q[r]]=i-1;
    14             r--;
    15         }
    16         q[++r]=i;
    17     }
    18     while (r>0)las[q[r--]]=n;
    19     for(int i=n;i>=1;i--){
    20         while (r>=0&&a[q[r]]>a[i]){
    21             pre[q[r]]=i+1;
    22             r--;
    23         }
    24         q[++r]=i;
    25     }
    26     while (r>0)pre[q[r--]]=1;
    27     ll ans = 0;
    28     for(int i=1;i<=n;i++){
    29         if(a[i]*(sum[las[i]]-sum[pre[i]-1])>=ans)
    30             ans = a[i]*(sum[las[i]]-sum[pre[i]-1]),l=pre[i],r=las[i];
    31     }
    32     printf("%lld
    %d %d",ans,l,r);
    33 }
    View Code

    poj 3494 

    给01矩阵,找最大的全是1的子矩阵

    枚举行,转化成直方图最大矩形面积。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 int n,m,a[2019][2019],cpp[2009][2009],q[2009],las[2009],pre[2009];
     6 int slove(int a[]){
     7     memset(las,0, sizeof(las));
     8     memset(pre,0, sizeof(pre));
     9     int l=0,r=0;
    10     for(int i=1;i<=m;i++){
    11         while (r>0&&a[q[r]]>a[i]){
    12             las[q[r]]=i-1;
    13             r--;
    14         }
    15         q[++r]=i;
    16     }
    17     while (r>0)las[q[r--]]=m;
    18     for(int i=m;i>=1;i--){
    19         while (r>=0&&a[q[r]]>a[i]){
    20             pre[q[r]]=i+1;
    21             r--;
    22         }
    23         q[++r]=i;
    24     }
    25     while (r>0)pre[q[r--]]=1;
    26     int ans = 0;
    27     for(int i=1;i<=n;i++)if(a[i]*(las[i]-pre[i]+1)>ans)ans = a[i]*(las[i]-pre[i]+1);
    28     return ans;
    29 }
    30 void init(){
    31     for(int i=1;i<=m;i++){
    32         for(int l=1,r;l<=n;l=r+1){
    33             r=l;
    34             if(a[l][i]==0)continue;
    35             while (a[r+1][i]==1)r++;
    36             for(int j=l;j<=r;j++)cpp[j][i]=r-j+1;
    37         }
    38     }
    39 }
    40 int main(){
    41     while (scanf("%d%d",&n,&m)!=EOF) {
    42         memset(a,0, sizeof(a));
    43         memset(cpp,0, sizeof(cpp));
    44         for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)scanf("%d", &a[i][j]);
    45         init();
    46         int ans = 0;
    47         for (int i = 1; i <= n; i++)
    48             ans = max(ans, slove(cpp[i]));
    49         printf("%d
    ", ans);
    50     }
    51 }
    View Code

     hdu 5033

    坐标轴上竖n个竿子,问你在(?,0)这个点向左向右能看到的角度范围。

    单调栈处理出来每个位置向左向右能看到的竿子。

    对于Xa<Xb<Xc这样的竿子来说,如果a能挡住b,那么a肯定能挡住c,所以pop(b)

    询问输出是换行的。。。我一开始输出的空格给我wrong answer...坑死我了,理论1A

    不memset 点的话答案会不对,,不知道为什么。

     1 #include <bits/stdc++.h>
     2 #define pb(x) push_back(x)
     3 using namespace std;
     4 typedef double db;
     5 const db pi=acos(-1);
     6 const int N = 2e5+5;
     7 struct point {
     8     db x,y;
     9     bool operator <(const point &k1)const {return x<k1.x;}
    10     int id;
    11 };
    12 point p[N];int que[N],lef[N],rig[N];db ans[N];
    13 int T,n,cas,q,x;
    14 int main(){
    15     scanf("%d",&T);
    16     while (cas++<T){
    17 //        memset(ans,0, sizeof(ans));
    18 //        memset(que,0, sizeof(que));
    19 //        memset(lef,0, sizeof(lef));
    20 //        memset(rig,0, sizeof(rig));
    21         memset(p,0, sizeof(p));
    22         scanf("%d",&n);
    23        for(int i=1;i<=n;i++){
    24            scanf("%lf%lf",&p[i].x,&p[i].y);
    25        }
    26        scanf("%d",&q);
    27        for(int i=1;i<=q;i++){
    28            scanf("%lf",&p[i+n].x);
    29            p[i+n].y=0;p[i+n].id=i;
    30        }
    31        sort(p+1,p+1+n+q);
    32        int r=0;
    33        for(int i=1;i<=n+q;i++){
    34            while (r>0&&p[que[r]].y<=p[i].y){
    35                r--;
    36            }
    37            while (r>1&&(p[que[r]].y-p[i].y)/(-p[que[r]].x+p[i].x)<=(p[que[r-1]].y-p[i].y)/(-p[que[r-1]].x+p[i].x)){
    38                r--;
    39            }
    40            lef[i] = que[r];
    41            que[++r] = i;
    42        }
    43        r=0;
    44        for(int i=n+q;i>=1;i--){
    45            while (r>0&&p[que[r]].y<=p[i].y){
    46                r--;
    47            }
    48            while (r>1&&(p[que[r]].y-p[i].y)/(p[que[r]].x-p[i].x)<=(p[que[r-1]].y-p[i].y)/(p[que[r-1]].x-p[i].x)){
    49                r--;
    50            }
    51            rig[i] = que[r];
    52            que[++r] = i;
    53        }
    54        for(int i=1;i<=n+q;i++){
    55             if(r=p[i].id){
    56                 ans[r] = atan((-p[lef[i]].x+p[i].x)/(p[lef[i]].y-p[i].y))+atan((p[rig[i]].x-p[i].x)/(p[rig[i]].y-p[i].y));
    57                 ans[r] = ans[r]*180/pi;
    58             }
    59        }
    60        printf("Case #%d
    ",cas);
    61        for(int i=1;i<=q;i++){
    62            printf("%.11f
    ",ans[i]);
    63        }
    64     }
    65 }
    66 /**
    67 3
    68 3
    69 1 2
    70 2 1
    71 5 1
    72 1
    73 4
    74  */
    View Code

     cf 1156E

    让你找

    满足这个的l,r的数量。

    显然我们可以先单调栈维护出来每个pi作为最大值能覆盖到的区间

    然后暴力找小的区间就行了。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int N = 2e5+5;
     4 int n,a[N],id[N],pre[N],las[N],q[N];
     5 int main(){
     6     ios::sync_with_stdio(false);
     7     cin>>n;
     8     for(int i=1;i<=n;i++)cin>>a[i],id[a[i]]=i;
     9     int l=0,r=0;
    10     for(int i=1;i<=n;i++){
    11         while(r>0&&a[q[r]]<a[i]) {
    12             las[q[r]] = i - 1;
    13             r--;
    14         }
    15         q[++r]=i;
    16     }
    17     while (r>0){las[q[r--]]=n;}
    18     for(int i=n;i>=1;i--){
    19         while(r>0&&a[q[r]]<a[i]){
    20             pre[q[r]]=i+1;
    21             r--;
    22         }
    23         q[++r]=i;
    24     }
    25     while (r>0)pre[q[r--]]=1;
    26     int ans = 0;
    27     for(int i=1;i<=n;i++){
    28         if(i-pre[i]<las[i]-i){
    29             for(int j=pre[i];j<i;j++){
    30                 if(id[a[i]-a[j]]>i&&id[a[i]-a[j]]<=las[i])
    31                     ans++;
    32             }
    33         }else{
    34             for(int j=i+1;j<=las[i];j++){
    35                 if(id[a[i]-a[j]]>=pre[i]&&id[a[i]-a[j]]<i)
    36                     ans++;
    37             }
    38         }
    39     }
    40     cout<<ans<<endl;
    41 }
    View Code
  • 相关阅读:
    学生管理系统后感
    数据库是什么鬼,怎么连接,怎么搞
    nIce 不看会后悔的o!
    那些年披巾斩浪的数据库
    day82
    day81
    day80
    day79
    day78
    day77
  • 原文地址:https://www.cnblogs.com/MXang/p/10771375.html
Copyright © 2020-2023  润新知