[BZOJ] 1660: [Usaco2006 Nov]Bad Hair Day 乱发节

1660: [Usaco2006 Nov]Bad Hair Day 乱发节

Time Limit: 2 Sec  Memory Limit: 64 MB
Submit: 1207  Solved: 591
[Submit][Status][Discuss]

Description

Input

* Line 1: 牛的数量 N。

 * Lines 2..N+1: 第 i+1 是一个整数,表示第i头牛的高度。

Output

* Line 1: 一个整数表示c[1] 至 c[N]的和。

Sample Input

6
10
3
7
4
12
2


输入解释:

六头牛排成一排,高度依次是 10, 3, 7, 4, 12, 2。

Sample Output

5

3+0+1+0+1=5

HINT

 

Source

Silver

 

Analysis

单调栈

= =我是先知道是什么再去学的怎么做的

那么我们现在有这么个数列 10 3 7 4 12 2

如下:

对于身高10米的奶牛(也就是 1 号),显然在 12 米的 5 号奶牛之前的奶牛都会被计数到 1 号奶牛那里

定义 see( i ) 为每个奶牛能看到的最远的位置

那么 c 就是 see(i)-i ,最后一次性统计或者什么都很方便

于是某些东西就有了单调性

突然发现自己解释不清

建立一个单调栈,保持栈底的元素比栈顶的大

那么从右往左扫描的时候,将元素一个个按这个法则压进去,如果栈顶元素比当前元素 “高” ,就弹出。

当栈顶元素比当前元素大的时候,栈顶元素就是那个 “能挡住 1 号的 5 号”

那么当前元素的 see 值就是栈顶元素的位置-1

自行体悟!!

 

Code

 1 /**************************************************************
 2     Problem: 1660
 3     User: child
 4     Language: C++
 5     Result: Accepted
 6     Time:108 ms
 7     Memory:24724 kb
 8 ****************************************************************/
 9  
10 #include<cstdio>
11 #include<iostream>
12 #define maxn 1000000
13 using namespace std;
14  
15 long long high[maxn],see[maxn],n,ans;
16 long long stack[maxn],st_poi;
17  
18 int main(){
19     scanf("%lld",&n);
20     for(int i = 1;i <= n;i++){
21         scanf("%lld",&high[i]);
22     }   
23      
24     for(int i = n;i >= 1;i--){
25         while(high[stack[st_poi-1]] < high[i] && st_poi)
26             st_poi--;
27         if(st_poi) see[i] = stack[st_poi-1]-1;
28         else see[i] = n;
29         stack[st_poi++] = i;
30     }
31      
32     for(int i = 1;i <= n;i++){
33 //      printf("%d ",see[i]);
34         ans += see[i]-i;
35     }
36      
37     printf("%lld",ans);
38      
39     return 0;
40 }
心情不好qwq

 

posted @ 2017-09-08 13:40  μSsia  阅读(155)  评论(0编辑  收藏  举报