题目描述
N个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的。
写一个程序计算出有多少对人可以互相看见。
输入输出格式
输入格式:
输入的第一行包含一个整数N (1 ≤ N ≤ 500 000), 表示队伍中共有N个人。
接下来的N行中,每行包含一个整数,表示人的高度,以毫微米(等于10的-9次方米)为单位,每个人的调度都小于2^31毫微米。这些高度分别表示队伍中人的身高。
输出格式:
输出仅有一行,包含一个数S,表示队伍中共有S对人可以互相看见。
输入输出样例
输入样例#1:
7 2 4 1 2 2 5 1
输出样例#1:
10
说明
数据制作: @w
代码:
栈模拟。
1 #include<cstdio> 2 using namespace std; 3 4 int n,Ans; 5 struct Stack 6 { 7 int tp,sz[500005]; 8 Stack() 9 { 10 tp=0; 11 } 12 void Del() 13 { 14 --tp; 15 } 16 int Get() 17 { 18 return sz[tp]; 19 } 20 bool Empty() 21 { 22 return tp==0; 23 } 24 void Insert(int x) 25 { 26 sz[++tp]=x; 27 } 28 }s; 29 30 void read(int &now) 31 { 32 now=0;char c=getchar(); 33 while(c<'0'||c>'9')c=getchar(); 34 while(c>='0'&&c<='9')now=now*10+c-'0',c=getchar(); 35 } 36 37 int main() 38 { 39 read(n); 40 int a; 41 while(n--) 42 { 43 read(a);int t=1; 44 while(a>=s.Get() && !s.Empty()) 45 {//当当前高度比栈顶元素大时,栈中元素要一直弹出直到栈顶大于等于当前高度 46 //(比当前小的都看不见后面的了) 47 //每次弹出Ans都++(比当前矮的可以看见当前元素,但不能看见以后的元素 so弹出) 48 //这里将所有等于当前元素的也一起弹出了,并记录弹出个数 49 if(s.Get()==a) ++t; 50 s.Del(),++Ans; 51 } 52 if(!s.Empty())//此时栈中还有 那一定是大于当前高度的,他们可以互相看见 53 ++Ans; 54 while(t--)//将原先等于当前的重新入栈 因为t初始=1,所以当前的也会算在内 入栈 55 s.Insert(a); 56 } 57 58 printf("%d",Ans); 59 return 0; 60 }