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;
    }
    
  • 相关阅读:
    线段树优化dp——牛客多校第一场I(好题)
    字符串dp——牛客多校第五场G
    凑出和相等的k组数,玄学结论——hdu6616
    主席树/线段树模拟归并排序+二分答案(好题)——hdu多校第4场08
    思维题+贪心——牛客多校第一场C
    线性基算贡献——19牛客多校第一场H
    俞敏洪语录
    睡眠长短决定寿命!人每天应该睡多少小时
    Java程序员从笨鸟到菜鸟之(三十一)大话设计模式(一)设计模式遵循的七大原则
    spring源码剖析(五)利用AOP实现自定义Spring注解
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4835648.html
Copyright © 2011-2022 走看看