zoukankan      html  css  js  c++  java
  • poj_3250 单调栈

    题目大意

        N头牛排成一列,每头牛A都能看到它前面比它矮的牛i,若前面有一个比他高的牛X,则X之前的牛j,A都无法看到。给出N头牛的高度,求出这N头牛可以看到牛的数目的总数。

    题目分析

        画图之后,可以很容易看出是典型的单调栈问题。单调栈问题中栈元素一般有两个属性:一是牛的索引位置,二是牛的高度。每次得到一个牛index的高度height之后,都和栈顶元素进行比较,若height > stack[top].height 则直接将(新牛的高度height,新牛的索引index)入栈,否则,弹栈,直到栈顶元素stack[top].height < height,再将(新牛的高度height,新牛的索引index)入栈。 
        在牛A被出栈的时候,可以获得牛A能够看到的牛的个数(即新入栈的牛B的索引index_b - 牛A的索引index_a)。最后记得清空栈元素来获得所有值。

    实现(c++)

    可以不使用单调栈

    #include<stdio.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<list>
    #include<set>
    #include<set>
    #include<map>
    #include<functional>
    #include<algorithm>
    using namespace std;
    const int kMax = 80005;
    
    //height 数组
    int height[kMax];
    
    //从i点向左看,第一个高度等于或者大于height[i]的数组下标
    int higher_index[kMax];
    
    long long int solve(int n){
    	int j;
    	long long result = 0;
    	for (int i = 0; i < n; i++){
    		j = i - 1;
    		while (j >= 0 && height[j] < height[i]){
    			j = higher_index[j];
    		}
    		higher_index[i] = j;
    		result += (i - j - 1);
    	}	
    	return result;
    }
    int main(){
    	int n;
    	scanf("%d", &n);
    	//题目要求从左向右看,将数组颠倒,然后换个方向,从右向左看,结果是一样的
    	for (int i = n - 1; i >= 0; i--){
    		scanf("%d", &height[i]);
    	}
    	long long int result = solve(n);
    	printf("%lld
    ", result);
    	return 0;
    }
    

    使用单调栈

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #define MAX_COW_NUM 80005
    int st[MAX_COW_NUM][2];
    int gCanSeeNum[MAX_COW_NUM];
    
    int main(){
    	int n;
    	scanf("%d", &n);
    	int height, top = -1;
    	long long sum = 0;
    	for (int i = 0; i < n; i++){
    		scanf("%d", &height);
    		while (top >= 0 && st[top][1] <= height){
    			gCanSeeNum[st[top][0]] = i - st[top][0] - 1;
    			sum += gCanSeeNum[st[top][0]];
    			top--;
    		}
    		top++;
    		st[top][0] = i;
    		st[top][1] = height;
    	}
    	while (top >= 0){
    		gCanSeeNum[st[top][0]] = n - st[top][0] - 1;
    		sum += gCanSeeNum[st[top][0]];
    		top--;
    	}
    	printf("%lld
    ", sum);
    	return 0;
    }
    

     使用单调栈2

    #include<stdio.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<list>
    #include<set>
    #include<set>
    #include<map>
    #include<functional>
    #include<algorithm>
    using namespace std;
    const int kMax = 80005;
    
    //height 数组
    int height[kMax];
    int mon_stack[kMax];
    long long int solve(int n){
    	int top = -1;
    	long long result = 0;
    	for (int i = 0; i < n; i++){
    		while (top >= 0 && height[mon_stack[top]] < height[i]){
    			top--;
    		}
    		if (top < 0)
    			result += i;
    		else
    			result += (i - mon_stack[top] - 1);
    		mon_stack[++top] = i;
    	}
    	return result;
    }
    int main(){
    	int n;
    	scanf("%d", &n);
    	//题目要求从左向右看,将数组颠倒,然后换个方向,从右向左看,结果是一样的
    	for (int i = n - 1; i >= 0; i--){
    		scanf("%d", &height[i]);
    	}
    	long long int result = solve(n);
    	printf("%lld
    ", result);
    	return 0;
    }
    
  • 相关阅读:
    tomcat的OutOfMemoryError内存溢出解决方法
    转:动态table分页(ORCALE)
    转: 根据屏幕分辨率,浏览器调用不同css
    转:只能选择GridView中的一个CheckBox(单选CheckBox)
    转:tomcat安全设置
    Tomcat内存设置详解
    Dos命令删除添加新服务
    卸载oracle 10g
    转:oracle:win7手工卸载oracle数据库11g
    win7 下安装oracle 10 g
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4835648.html
Copyright © 2011-2022 走看看