贪心+栈+队列类瞎操作

一.栈

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

 

posted @ 2018-11-06 09:30  flowphyl  阅读(233)  评论(0编辑  收藏  举报