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;
    }
    
  • 相关阅读:
    关于.NET2.0下的脱机文件App_Offline.htm文件
    VS2005中安装AJAX指南
    Ajax中“Sys未定义”错误的解决方法汇总
    GridView控件模板列中的按钮单击时,在RowDataBound事件中获取该行行号
    用户控件中使用User.Identity
    同一个页面中的不同Button分别验证某一部分输入控件
    hdu Tempter of the Bone
    acm steps chapter1总结
    ORACLE中的TOPN查询(TOPN分析),分页查询
    MySQL中如何实现select top n
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4835648.html
Copyright © 2011-2022 走看看