1660: [Usaco2006 Nov]Bad Hair Day 乱发节
Time Limit: 2 Sec Memory Limit: 64 MBSubmit: 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。
10
3
7
4
12
2
输入解释:
六头牛排成一排,高度依次是 10, 3, 7, 4, 12, 2。
Sample Output
5
3+0+1+0+1=5
3+0+1+0+1=5
HINT
Source
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 }