COI2007 Patrik 音乐会的等待 洛谷P1823

Description

N个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。队列中任意两个人A和B,如果他们是相邻或他们之间没有人比A或B高,那么他们是可以互相看得见的。


写一个程序计算出有多少对人可以互相看见。


Input

输入的第一行包含一个整数N,表示队伍中共有N个人。接下来的N行中,每行包含一个整数,表示人的高度,以毫微米(等于10的-9次方米)为单位,每个人的调度都小于2^31毫微米。这些高度分别表示队伍中人的身高。


Output

输出仅有一行,包含一个数S,表示队伍中共有S对人可以互相看见。


Hint

1≤N≤500000。


Solution

最开先是写的一个很简单的数组模拟单调栈,加了快读Luogu上面专门设置的三个点还是超时了。。。后来看了官方题解,维护了一个数对pair的单调栈。值得注意的是,这里的pair含义是pair<身高,人数>。


由于我们知道,当这个人前后视线里面遇到了一个极其高的B,那么B后面的所有人,这个人都是看不到的。所以单调栈是降序的,当他和一个人聊完天以后就弹出这一个人,弹出后如果栈没空他就可以再聊一个,然后再让这个人进栈。当然,如果两个人身高相同的话,还是能看到这个人后面的人啦quqqq。

TLE了最后三个点的80分代码:

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define maxn 500005
using namespace std;
int stackk[maxn],cnt;
int n,x,j;
long long ans;
void quickread(int &x){
    char c;
    while((c=getchar())<'0'||c>'9');
    for(x=0;c>='0'&&c<='9';c=getchar()){
    	x=x*10+c-'0';
	}
}
int main(){
    quickread(n);
    for(int i=1;i<=n;i++){
        quickread(x);
        j=1;
        while(x>stackk[cnt]&&cnt>0){
            cnt--;
            ans++;
        }
        while(x==stackk[cnt]&&cnt>0){
            cnt--;
            ans++;
            j++;
        }
        if(cnt!=0){
        	ans++;
        }
        cnt+=j;
        stackk[cnt]=x;
    }
    printf("%lld\n",ans);
} 

AC代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<stack>
#define int long long
#define s pair<int,int> 
using namespace std;
stack<s>stk;
int n,x,ans;
void quickread(int &x){
    char c;
    while((c=getchar())<'0'||c>'9');
    for(x=0;c>='0'&&c<='9';c=getchar()){
    	x=x*10+c-'0';
	}
}
signed main(){
	quickread(n);
	for(int i=1;i<=n;i++){
		quickread(x);
		s p(x,1);
		for(;!stk.empty()&&stk.top().first<=x;stk.pop()){
        	ans+=stk.top().second;
        	if(stk.top().first==x){
        		p.second+=stk.top().second;	
			}
        }
        if(!stk.empty())ans++;
      	stk.push(p);
	}
	printf("%lld",ans);
	return 0;
} 
posted @ 2018-11-30 17:24  虚拟北方virtual_north。  阅读(155)  评论(0编辑  收藏  举报