1. 程式人生 > 其它 >P3467 [POI2008]PLA-Postering 題解

P3467 [POI2008]PLA-Postering 題解

這道題首先可以發現,寬度是完全沒有用處的,所以可以忽略不計。

然後在貼海報時,可以發現:如果某一個點與前面某一個點相同,而且這兩個點中間沒有比他們低的點,那麼可以節省一張海報。

啥意思?比如說:

1 4 2 1 2 3

處理時,由於兩個 1 中間沒有比 1 低的,那麼他們可以共享一張海報(使用公共邊),而兩個 2 之間就不行,因為裡面有一個搞事情的 1 ,使得兩個 2 不能共用一張海報。

而此時問題就變成了如何處理兩個 2 中間的 1 ?其實當出現了一個 1 的時候,前面的所有比 1 大的數全部沒有用處了,而這個操作恰好可以使用單調棧維護。

我們維護一個單調遞增棧,棧內元素單調遞增,加入新資料時彈棧完畢後只需要判斷一下當前棧頂元素是否與加入元素相等就可以了,如果是相等的,不需要新增一張海報,否則需要新增一張海報。

程式碼:

#include<bits/stdc++.h>
using namespace std;

const int MAXN=250000+10;
int n,h[MAXN],p,ans,sta[MAXN];

int read()
{
	int sum=0,fh=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') fh=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
	return sum*fh;
}

int main()
{
	n=read();
	for(int i=1;i<=n;i++) {read();h[i]=read();}
	p=0;
	for(int i=1;i<=n;i++)
	{
		ans++;
		while(p!=0&&h[sta[p]]>h[i]) p--;
		if(h[sta[p]]==h[i]) ans--;
		sta[++p]=i;
	}
	cout<<ans<<"\n";
	return 0;
}