zoukankan      html  css  js  c++  java
  • 贪心+栈+队列类瞎操作

    一.栈

    1. luogu P3467 [POI2008]PLA-Postering

      这个题听说是单调栈的入门题qwq 

      自己想的时候想到了用单调栈维护高度 依次入栈,while(即将入栈的高度小于栈顶),就弹出栈顶;

      但是具体怎么记答案还是没想到 于是又想了一个玄学做法,用桶记录所有出现过的高度 相邻两高度ans++; 后来发现这样没法记是否连贯 要记录就太麻烦了 不得不弃

      正解和第一个思路有关

      记录答案初始ans=n;  依旧处理栈顶,  如果栈顶==w ans--;

      因为:1.对于高度不同的两个 必须用两张覆盖  2.高度相同可以用一张拉直覆盖

      所以说在弹出时 栈顶!=w 就不会使答案减少

      

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<stack>
     7 #define N 250100
     8 using namespace std;
     9 stack<int>st;
    10 int d[N],w[N];
    11 int n,ans;
    12 int main()
    13 {
    14     scanf("%d",&n); ans=n;
    15     for(int i=1;i<=n;i++)
    16     {
    17         scanf("%d%d",&d[i],&w[i]);
    18         while(!st.empty()&&st.top()>=w[i])
    19         {
    20             if(st.top()==w[i]) ans--;
    21             st.pop();
    22         }
    23         st.push(w[i]);
    24     }
    25     printf("%d",ans);
    26     return 0;
    27 }
    3467

     2. luoguP4147 玉蟾宫

      听说这还带一个最大子矩阵的模板

      然而蒟蒻的我只想到了n^3的暴力枚举

      首先预处理: 对于每一行向上处理可以走的步数     if(x=='F') pos[i][j]=pos[i-1][j]+1;

      然后对每一行 x 维护一个单调栈 记录 pos[x][i] 和 可延展的宽度

      如果 st.top().h>pos[x][i] 就弹栈 并处理更新答案

      最后注意的是输入字符串的1mol多空格 用getchar()解决

      一个很好的blog

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<algorithm>
     6 #include<stack>
     7 #include<cctype>
     8 #define ll long long
     9 #define N 2010
    10 using namespace std;
    11 struct node
    12 {
    13     int h,w;
    14 }a[N];
    15 stack<node> st;
    16 int n,m;
    17 int ans,anss;
    18 int pos[N][N];
    19 void red(int &x)
    20 {
    21     int f=1;x=0;char c=getchar();
    22     while(!isdigit(c)) {if(c=='-') f=-1; c=getchar();}
    23     while(isdigit(c)) {x=x*10+c-'0'; c=getchar();}
    24     x*=f;
    25 }
    26 char get()
    27 {
    28     char c=getchar();
    29     while(c!='F'&&c!='R') c=getchar();
    30     return c;
    31 }
    32 void cal(int x)
    33 {
    34     int tmp;
    35     st.push((node){pos[x][1],1});
    36     for(int i=2;i<=m;i++)
    37     {
    38         tmp=0;
    39         while(!st.empty()&&st.top().h>=pos[x][i])
    40         {
    41             tmp+=st.top().w;
    42             ans=max(ans,st.top().h*tmp);
    43             st.pop();
    44         }
    45         st.push((node){pos[x][i],tmp+1});
    46     }
    47     tmp=0;
    48     while(!st.empty())
    49     {
    50         tmp+=st.top().w;
    51         anss=max(anss,st.top().h*tmp);
    52         st.pop();
    53     }
    54     ans=max(ans,anss);
    55 }
    56 int main()
    57 {
    58     red(n); red(m);
    59     for(int i=1;i<=n;i++)
    60         for(int j=1;j<=m;j++)
    61         {
    62             char x=get();
    63             if(x=='F') pos[i][j]=pos[i-1][j]+1;
    64         }
    65     for(int i=1;i<=n;i++) cal(i);
    66     printf("%d",ans*3);
    67     return 0;
    68 }
    4147

     3. luogu P3668 [USACO17OPEN]Modern Art 2

      一来终于反应觉得是个栈 但始终感觉不对:每一次我们要找的距离最远的配对的两个数 所以差点掉到想deque的坑里

      后来索性放弃想数据结构 考虑裸贪心 

      想到记录每个颜色出现的第一次和最后一次位置

      但如何维护呢? 不由得又回到了想栈 但是怎么维护进栈的次序达到一层一层处理呢?

      然后我就凉了

      正解高明之处在于:每次循环准备进栈的时候, i 直接跳过上一次进栈的颜色出现的最后位置 相当于 保证每次考虑的都是同层的颜色

      且考虑完同层后直接按顺序进入下一层

      实现如下:

    for(int i=1;i<=n;i++)
    {
        .........
        st.push((node){i,last[a[i]],1});
        i=last[a[i]];
    }

      还有一点在于记录答案,每次遇到区间内满足的点 (即层数+1)于是入栈的时间也累加1,即 tmp.t+1

     1 #include<bits/stdc++.h>
     2 #define N 200100
     3 using namespace std;
     4 struct node
     5 {
     6     int x,y,t;
     7 }tmp;
     8 stack<node>st;
     9 int n;
    10 int a[N],last[N];
    11 int main()
    12 {
    13     scanf("%d",&n);
    14     for(int i=1;i<=n;i++)
    15     {
    16         scanf("%d",&a[i]);
    17         last[a[i]]=i;
    18     }
    19     for(int i=1;i<=n;i++)
    20     {
    21         if(!a[i]) continue;
    22         st.push((node){i,last[a[i]],1});
    23         i=last[a[i]];
    24     }
    25     int ans=0;
    26     while(!st.empty())
    27     {
    28         tmp=st.top();
    29         ans=max(ans,tmp.t);
    30         st.pop();
    31         for(int i=tmp.x+1;i<=tmp.y-1;i++)
    32         {
    33             if(a[i]==a[tmp.x]) continue;
    34             if(!a[i])
    35             {
    36                 printf("-1");
    37                 return 0;
    38             }
    39             if(a[i]!=a[tmp.x]&&last[a[i]]>last[a[tmp.x]])
    40             {
    41                 printf("-1");
    42                 return 0;
    43             }
    44             st.push((node){i,last[a[i]],tmp.t+1});
    45             i=last[a[i]];
    46         }
    47     }
    48     printf("%d",ans);
    49     return 0;
    50 }
    3668
  • 相关阅读:
    CentOS安装python setuptools and pip
    Memcached集群:Magent缓存代理使用
    PHP上传类 图片上传 upload class实现image crop resize 缩略图
    CentOS全自动一键安装PHP,MySQL,phpmyadmin与Nginx
    【转】浅析linux内存模型
    【转】深入浅出异步I/O模型
    【转】客户/服务器程序设计范式
    【转】如何保证睡眠的情况下把各种事情做好
    【转】非教育网中IPv4网络访问IPv6资源
    busybox介绍
  • 原文地址:https://www.cnblogs.com/kylara/p/9913294.html
Copyright © 2011-2022 走看看