2019年秋季学期第四周周总结——YCG

周任务:

算法主题:

单调栈

具体任务:

在这里插入图片描述对于单调栈还是比较熟悉的,完成任务过程出现了一些困难——都是源自自己对题意的理解,单调栈倒是没啥问题。
POJ2559(一维单调栈维护直方图的面积)
链接
代码:

#include"iostream"
using namespace std;
const int maxn = 100000+5;
int s[maxn],H[maxn],top,N;
int L[maxn],R[maxn];
int main(){
	while(~scanf("%d",&N)){
		if(N==0)break;
		top = 0;
    for(int i = 1;i <= N;i++)
    scanf("%d",&H[i]);
    for(int i = 1;i <= N;i++){
    	while(top>0&&H[s[top]]>=H[i])top--;
    	if(top==0)L[i] = 0;
    	else L[i] = s[top];
    	s[++top] = i;
	}
	top = 0;
	for(int i = N;i >= 1;i--){
    	while(top>0&&H[s[top]]>=H[i])top--;
    	if(top==0)R[i] = N;
    	else R[i] = s[top] - 1;
    	s[++top] = i;
	}       
	long long ans = 0;
	for(int i = 1;i <= N;i++)
	ans = max(ans,(long long)1*(R[i] - L[i])*H[i]); 
	cout  << ans <<endl;
	}                               
	 
	return 0;
}               

POJ3494(二维单调栈维护直方图面积)
链接
代码:

#include"iostream"
#include"stdio.h"
#include"cstring"
using namespace std;
int N,M;
int a[2005][2005],up[2005],s[2005],l[2005],r[2005],top;
int main(){
	while(~scanf("%d%d",&N,&M)){
		int ans = 0;
		memset(up,0,sizeof(up));
		for(int i = 1;i <= N;i++){
		   for(int j = 1;j <= M;j++){
		   	scanf("%d",&a[i][j]);
		   	if(a[i][j]==0)
		   	up[j] = 0;
		   	else 
		   	up[j]++;
		   }
		      top = 0;
			  for(int j = 1;j <= M;j++){
		          while(top > 0&&up[s[top]] >= up[j])top--;
				  if(top==0)l[j] = 0;
				  else l[j] = s[top];
				  s[++top] = j;
			  }
			  top = 0;
		      for(int j = M;j >= 1 ;j--){
		          while(top > 0&&up[s[top]] >= up[j])top--;
				  if(top==0)r[j] = M;
				  else r[j] = s[top] - 1;
				  s[++top] = j;
			  }
			  for(int j = 1;j <= M;j++)
			  ans = max(ans,(r[j]-l[j])*up[j]);	
			
	}
		printf("%d\n",ans);
}   
return 0;
}

2019牛客多校训练营第一场A(单调栈记录序列变化趋势)
链接
代码:

#include"bits/stdc++.h"
using namespace std;
const int maxn = 1e5+5;
int N,a[maxn],b[maxn],S1[maxn],S2[maxn];
int main(){
    while(~scanf("%d",&N)){
        for(int i = 1;i <= N;i ++)
            scanf("%d",&a[i]);
        for(int i = 1;i <= N;i++)
            scanf("%d",&b[i]);
           int top1 = 0,top2 = 0,ans = N;
        for(int i = 1;i <= N;i++){
           while(top1>0&&a[S1[top1]]>a[i])top1--;
            S1[++top1] = i;
           while(top2>0&&b[S2[top2]]>b[i])top2--;
            S2[++top2] = i;
            if(top1==top2)continue;
            else{
                ans = i - 1;
                break;
            }
        }
        printf("%d\n",ans);
    }
    
    return 0;
}

2019牛客多校训练营第二场H(单调栈求二维直方图面积,题目要求第二大,就要加入最大的内含最大矩形)
链接
代码:(这是我不太喜欢的STL实现)

#include"bits/stdc++.h"
using namespace std;
int N,M,m1 = 0,m2 = 0,a[1005][1005],up[1005][1005]={0};
void Ud(int x,int y){
    int sum = x*y;
    if(sum > m1){
        m2 = m1;
        m1 = sum;
    }
    else if(sum>m2) m2 = sum;
}
int main(){
    scanf("%d%d",&N,&M);
    for(int i = 1;i <= N;i++)
        for(int j = 1;j <= M;j++){
            scanf("%1d",&a[i][j]);
             
        }
    for(int i = 1;i <= N;i++){
        for(int j = 1;j <= M;j++){
           if(a[i][j]==0)up[i][j] = 0;
           else up[i][j] = up[i-1][j] + 1;
        }
    }
    for(int i = 1;i <= N;i++){
          stack<int> S;
            S.push(0);
            for(int j = 1;j <= M+1;j++){
                while(up[i][S.top()]>up[i][j]){
                int pos = S.top();
                    S.pop();
                int h = up[i][pos];
                int w = j - S.top() - 1;
                    //cout <<pos<<" "<<j<<" "<<h<<endl;
                 Ud(w,h);
                 Ud(w-1,h);
                 Ud(w,h-1);
                }
                S.push(j);
            }
        }
    cout << m2;
    return 0;
}

2019牛客多校训练营第八场A——(单调栈维护非包含子矩形)
链接
代码:

#include <stdio.h>
#include <stack>
using namespace std;
char s[3005][3005];
int MatrixBottom[3005][3005],up[3005],N,M,ans = 0;  
int main() {
    scanf("%d%d", &N, &M);
    for (int i = 1; i <= N; i++) {        
    scanf("%s", s[i]); 
    }    
    for(int i = 1; i <= N; i++) { 
        for(int j = 0; j < M; j++) {     
               if(s[i][j] == '0')     
                up[j] = 0; 
               else               
               up[j]++;        
       }     
     stack<int> S;    
     for(int j = 0; j <= M; j++) {       
          while(!S.empty() && up[S.top()] > up[j]) {           
               int t = S.top();                
               S.pop();                
               int l;           
               while(!S.empty() && up[S.top()] == up[t]) S.pop();                     
               if(S.empty()) l = 0;                
               else l = S.top() + 1;                           
               if(MatrixBottom[l][j - 1] != i) ans++;                
               MatrixBottom[l][j - 1] = i + 1;            
          }            
          S.push(j);        
       }  
    }   
    printf("%d\n", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值