1. 程式人生 > >rqnoj 460單調佇列-1

rqnoj 460單調佇列-1

http://www.rqnoj.cn/Problem_460.html
題意:n個人站成一隊,每兩個人之間如果沒有比一個高的就說明二者能互相看到,問有多少對人能互相看到對方。。

分析:單調佇列,沒的說。。。但是相同高度要特殊處理一下, 這裡我是將連續的相同高度的存到一起並記錄個數。。連續相同高度的這一堆肯定互相能看到,而且都能看到前面和後面的。。。

程式碼:

#include<iostream>
using namespace std;

const int N=600010;
int n, a[N], q[N], qn;

int main()
{
	int i, j, k, x, ans;
	while(scanf("%d", &n)!=EOF)
	{
		qn = 0;
		ans = 0;
		for(i=0; i<n; i++)
		{
			scanf("%d", &x);
			while(qn>=1 && x>q[qn-1])
			{
				ans += a[qn-1]*(a[qn-1]-1)/2;
				if(qn>=2)
					ans += a[qn-1];
				ans += a[qn-1];
				qn--;
			}
			if(qn!=0 && x==q[qn-1])
				a[qn-1]++;
			else
			{
				a[qn] = 1;
				q[qn++] = x;
			}
		}
		while(qn>=2)
		{
			ans += a[qn-1]*(a[qn-1]-1)/2;
			ans += a[qn-1];
			qn--;
		}
		ans += a[0]*(a[0]-1)/2;
		printf("%d\n", ans);
	}
	return 0;
}

/*
#include<iostream>
using namespace std;

const int N=500100;
int n, a, sum;
int q[N], head, tail;

int main()
{
	int i, j, k;
	scanf("%d", &n);
	head = tail = 0;
	sum = 0;
	for(i=0; i<n; i++)
	{
		scanf("%d", &a);
		while(head<tail && q[tail-1]<a)
		{
			sum++;
			tail--;
			for(j=tail-1; j>head && q[j]==q[tail]; j--)
				sum++;
			if(tail>head)
				sum++;
		}
		q[tail++] = a;
	}
	while(tail>head+1)
	{
		//sum++;
		tail--;
		for(j=tail-1; j>head && q[j]==q[tail]; j--)
				sum++;
		if(tail>head)
			sum++;
	}
	printf("%d\n", sum);
	return 0;
}
*/