【題解】 逛畫展

題目來源:洛谷

題目描述

博覽館正在展出由世上最佳的 M 位畫家所畫的圖畫。

wangjy想到博覽館去看這幾位大師的作品。

可是,那裏的博覽館有一個很奇怪的規定,就是在購買門票時必須說明兩個數字,

a和b,代表他要看展覽中的第 a 幅至第 b 幅畫(包含 a 和 b)之間的所有圖畫,而門票

的價錢就是一張圖畫一元。

爲了看到更多名師的畫,wangjy希望入場後可以看到所有名師的圖畫(至少各一張)。

可是他又想節省金錢。。。

作爲wangjy的朋友,他請你寫一個程序決定他購買門票時的 a 值和 b 值。

輸入格式

第一行是 N 和 M,分別代表博覽館內的圖畫總數及這些圖畫是由多少位名師的畫

所繪畫的。

其後的一行包含 N 個數字,它們都介於 1 和 M 之間,代表該位名師的編號。

輸出格式

a和 b(a<=b) 由一個空格符所隔開。

保證有解,如果多解,輸出a最小的。

輸入輸出樣例

輸入 #1
12 5
2 5 3 1 3 2 4 1 1 5 4 3
輸出 #1
2 7

數據範圍

約定 30%的數據N<=200 , M<=20

60%的數據N<=10000 , M<=1000

100%的數據N<=1000000 , M<=2000

思路:

deque

我發現用deque來做思路好清晰,拿樣例來說吧
vis[i]:i在隊列中出現過幾次
cnt:隊列裏有幾位名畫家
樣例:
2 5 3 1 3 2 4 1 1 5 4 3

-2入隊,vis[2]=1,cnt=1

q:2

-5入隊,vis[5]=1,cnt=2

q:2 5

-3入隊,vis[3]=1,cnt=3

q:2 5 3

-1入隊,vis[1]=1,cnt=4

q:2 5 3 1

-3入隊,vis[3]=2,cnt=4

q:2 5 3 1 3

-2入隊,vis[2]=2,cnt=4

q:2 5 3 1 3 2

此時隊頭已經有1個2了,所以把隊頭彈出,vis[2]=1,cnt=4

q:5 3 1 3 2

-4入隊,vis[4]=1,cnt=5

q:5 3 1 3 2 4

此時cnt=m,隊列裏包括了所有的名畫家,可以記錄答案
ansl=2 ansr=7(怎麼記錄?隊列類型用結構體就行了)

-1入隊,vis[1]=2,cnt=5
此時cnt=m,可是不能更新答案,因爲現在買票28還不如剛纔的27,所以加個判斷

q:5 3 1 3 2 4 1

-1入隊,vis[1]=3,cnt=5

q:5 3 1 3 2 4 1 1

-5入隊,vis[5]=2,cnt=5

q:5 3 1 3 2 4 1 1 5

我們發現隊頭有個5,可以彈出

q:3 1 3 2 4 1 1 5

此時隊頭的3也可以彈出,因爲隊列裏面有2個3,vis[3]=1,cnt=5

q:1 3 2 4 1 1 5

隊頭的1也可以彈出,因爲隊列裏有3個1,
vis[1]=2,cnt=5

q:3 2 4 1 1 5

此時還不能更新答案,因爲510的長度還沒有小於27的長度,題目意思是如果多解,輸出a最小的

-4入隊,vis[4]=2,cnt=5

q:3 2 4 1 1 5 4

-3入隊,vis[3]=2,cnt=5

q:3 2 4 1 1 5 4 3

彈出隊頭的3,vis[3]=1,cnt=5

q:2 4 1 1 5 4 3

詳情見代碼:

#include<bits/stdc++.h>
using namespace std;
int n,m,a[1000010],vis[2010],ansl=0,ansr=9999999;
struct node{
	int num;
	int id;
}e;
deque <node> q;
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	int cnt=0;
	for (int i=1;i<=n;i++)
	{
		e.num=a[i]; e.id=i;
		q.push_back(e);
		if (vis[a[i]]==0) cnt++;
		vis[a[i]]++;
		while (q.size()!=1&&q.front().num==q.back().num) //隊尾與隊頭相同,彈出隊頭 
		{
			vis[q.front().num]--;
			if (vis[q.front().num]==0) cnt--;
			q.pop_front(); 
		}
		while (vis[q.front().num]>1) //隊頭元素值在隊裏的數量超過1,可以彈出 
		{
			vis[q.front().num]--;
			if (vis[q.front().num]==0) cnt--;
			q.pop_front();
		}
	    if (cnt==m)
		{
			if (q.back().id-q.front().id<ansr-ansl)
			  ansl=q.front().id,ansr=q.back().id;
		} 
	}
	printf("%d %d\n",ansl,ansr);
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章